标签:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6375 Accepted Submission(s): 2947
题意:统计一个字符串的所有前缀在字符串中出现的次数的和
分析:next数组的运用,因为next数组可以表示以当前坐标的前一个字符结尾的字符串的前缀和后缀有多少个字符相等
举个例子,有一个字符串
0 1 2 3 4 5 6 7 8 9 10 11 12 13
a b c d a b d a b c d a b
-1 0 0 0 0 1 2 0 1 2 3 4 5 6
可见当i=9时,前缀ab和当前的abcdabdab最后的ab相等,所以长度为2,本应该答案是+1,但是想一想,既然ab都匹配了,那么a也会是匹配的,所以答案应该+2,发现这难道
不就是next[i]的值吗?所以说,只用加next[i]的值就行了,因为当前字符匹配完成之后,前面的字符也被匹配了。
所以最后的答案=字符串长度(前缀的个数)+每一个非0的next[]数组的值
但是这里要注意一点就是说,当next[i]+1==next[i+1]的时候,说明后面的字符会继续匹配下去,这种情况就不要加了,因为会重复统计。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<string> #include<iostream> #include<cstring> #include<cmath> #include<stack> #include<queue> #include<vector> #include<map> #include<stdlib.h> #include<algorithm> #define LL __int64 #define FIN freopen("in.txt","r",stdin) using namespace std; const int MAXN=200000+5; const int MOD=10007; int n; int nex[MAXN]; char str[MAXN]; void getnext() { int j=0,k=-1; nex[0]=-1; while(j<=n) { if(k==-1 || str[j]==str[k]) nex[++j]=++k; else k=nex[k]; } } int main() { //FIN; int kase; scanf("%d",&kase); while(kase--) { int ans=0; scanf("%d %s",&n,str); getnext(); for(int i=0;i<=n;i++) ans=(ans+nex[n]+n)%MOD; for(int i=0;i<n;i++) { if(nex[i]>0 && (nex[i]+1)!=nex[i+1]) ans=(ans+nex[i])%MOD; } printf("%d\n",ans); } return 0; }
HDU 3336 Count the string (KMP next数组运用——统计前缀出现次数)
标签:
原文地址:http://www.cnblogs.com/clliff/p/4725772.html