本题要求所给字符串的前缀在整个字符串中出现的次数的累加和。KMP算法的运用。
容易联想到KMP算法中的next[]数组,当next[i]>0时可以理解为i前面的next[]个字符组成的字符串对应一个前缀。此外长度为n的字符串有n个前缀。
所以res等于n加上所有next值大于0的元素的个数。
例如:abab
那么他的前缀有a , ab ,aba , abab。
对应的在原串中的个数为a有2个,ab有2个,aba有1个,abab有1个。
那么总数是6。
思路:对这个字符串求出Next数组,那么对于每个Next[i] = k ,那么我们就知道前缀0 -> k - 1处有一个匹配。那么累加即可。
那么只需根据Next数组匹配成功的个数进行累加即可。
/********************** * author:crazy_石头 * Pro:HDOJ 3336 * algorithm: KMP * Judge Status:Accepted * Memory:1246K * Time:46ms * date:2013/11/01 ***********************/ #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> using namespace std; #define rep(i,h,n) for(int i=(h);i<=(n);i++) const int maxn=200000+5; int next[maxn]; char p[maxn]; int n,test;//主串的串长; inline void getNext(char *p,int *next) { int i,j,m; i=0,j=-1; next[0]=-1; m=strlen(p); while(i<m) { if(j==-1||p[i]==p[j]) i++,j++,next[i]=j; else j=next[j]; } } int main() { scanf("%d",&test); while(test--) { scanf("%d",&n); scanf("%s",p); getNext(p,next); int res=n; rep(i,0,n) { if(next[i]>0) res=(res+1)%10007; } printf("%d\n",res); } return 0; } |
* This source code was highlighted byYcdoiT. ( style: Friend )