题库链接http://acm.hdu.edu.cn/showproblem.php?pid=3336
这道题是KMP的next数组的一个简单使用,首先要理解next数组的现实意义:next[i]表示模式串的前i个字符所组成的字符串的最长前缀后缀匹配长度,就比如对于字符串"abcdabe",它的next[3]=0,因为前三个字符构成的字符子串"abc"前后缀最长匹配长度为0,而next[6]=2,因为对于子串"abcdab",它的前缀后缀最大可以匹配出"ab",长度为2,对应了它的前缀后缀最大匹配长度。
对于这道题,我们从1位置开始遍历整个next数组,首先每一个前缀串自身都对答案有1的贡献,所以首先ans++,此外,当与到next[i]数值大于0的位置,说明前i个字符组成的子串有大于零的前缀后缀匹配,即前缀串在该位置重复出现了一次,所以此时ans再加1。
详见代码:


#includeusing namespace std; char s[200010]; int t,n,nex[200010]; int ans; void getNex(){ nex[0]=-1; int k=-1,j=0; while(j<n){ if(k==-1||s[j]==s[k]){ ++j;++k; nex[j]=k; } else k=nex[k]; } } int main(){ scanf("%d",&t); while(t--){ ans=0; scanf("%d%s",&n,s); getNex(); for(int i=1;i<=n;i++){ ans++; if(nex[i]!=0) ans++; ans%=10007; } printf("%d\n",ans); } return 0; }