题意:求字串中【前缀+跟前缀相同的子串】的个数?
Sample Input
1
4
abab
Sample Output
6
abab:包括2个a,2个ab,1个aba,1个abab
这里要用到next值的意义:
next[i]表示前i个字符所组成的字符串的最大前后缀匹配长度
举个例子:
![](http://dl.iteye.com/upload/attachment/510191/7a8669e4-5a51-397c-94f3-fa3bae38ab37.jpg)
next[5]=2, 表示下标5前面那个字符串abcab的前后缀匹配的最大长度是2,显然就是ab了
回到本题:
所求=字串的前缀个数+与前缀相同的子串
问题可以部分转化为:每个前缀的最大前后缀匹配问题
继续用上面的例子:
第一步:
![](http://dl.iteye.com/upload/attachment/510195/1b8b67fd-40db-3a18-8c80-ff17762f4098.jpg)
对于这段子串,next[5]=2,然后后面不符合next值的递增规律了。
所以对于abcab,长度为2的后缀,即ab与前缀匹配
所以+1个ab,注意还要+1个a,既然后缀ab跟前缀ab匹配,则必有a跟前缀匹配。
也就是+2个了,其实实际上+next[5]就可以了,因为这是最长前后缀匹配长度
第二步:
![](http://dl.iteye.com/upload/attachment/510199/11a1db9e-4748-3315-a604-cacfa40cc612.jpg)
对于这段子串:
next[6]=1,然后后面不符合next值的递增规律了。
所以对于abcaba,长度为1的后缀,即a与前缀匹配。
所以+1个a,也就是+next[6]了。
第三步:
![](http://dl.iteye.com/upload/attachment/510202/4bcf5e18-3904-37d1-80d5-d44c9bd5fc1f.jpg)
对于整个串:
next[12]=4后面没有了
所以对于整个串:abcabacbabca,长度为4的后缀跟前缀匹配
所以+1个abca,+1个abc,+1个ab,+1个a,总共+4个,也就是+next[12]了
最后:
好了,刚刚一共+了7个与前缀匹配的子串
上面说了题目是求:字串的前缀个数+与前缀相同的子串个数
与前缀相同的子串个数就是7个了
然后字串的前缀个数当然就是整个串的长度了,那么就是12个
Sample Input
1
4
abab
Sample Output
6
abab:包括2个a,2个ab,1个aba,1个abab
这里要用到next值的意义:
next[i]表示前i个字符所组成的字符串的最大前后缀匹配长度
举个例子:
![](http://dl.iteye.com/upload/attachment/510191/7a8669e4-5a51-397c-94f3-fa3bae38ab37.jpg)
next[5]=2, 表示下标5前面那个字符串abcab的前后缀匹配的最大长度是2,显然就是ab了
回到本题:
所求=字串的前缀个数+与前缀相同的子串
问题可以部分转化为:每个前缀的最大前后缀匹配问题
继续用上面的例子:
第一步:
![](http://dl.iteye.com/upload/attachment/510195/1b8b67fd-40db-3a18-8c80-ff17762f4098.jpg)
对于这段子串,next[5]=2,然后后面不符合next值的递增规律了。
所以对于abcab,长度为2的后缀,即ab与前缀匹配
所以+1个ab,注意还要+1个a,既然后缀ab跟前缀ab匹配,则必有a跟前缀匹配。
也就是+2个了,其实实际上+next[5]就可以了,因为这是最长前后缀匹配长度
第二步:
![](http://dl.iteye.com/upload/attachment/510199/11a1db9e-4748-3315-a604-cacfa40cc612.jpg)
对于这段子串:
next[6]=1,然后后面不符合next值的递增规律了。
所以对于abcaba,长度为1的后缀,即a与前缀匹配。
所以+1个a,也就是+next[6]了。
第三步:
![](http://dl.iteye.com/upload/attachment/510202/4bcf5e18-3904-37d1-80d5-d44c9bd5fc1f.jpg)
对于整个串:
next[12]=4后面没有了
所以对于整个串:abcabacbabca,长度为4的后缀跟前缀匹配
所以+1个abca,+1个abc,+1个ab,+1个a,总共+4个,也就是+next[12]了
最后:
好了,刚刚一共+了7个与前缀匹配的子串
上面说了题目是求:字串的前缀个数+与前缀相同的子串个数
与前缀相同的子串个数就是7个了
然后字串的前缀个数当然就是整个串的长度了,那么就是12个
加起来就是答案:19。
到这里,有些同学就要问了,为什么next[4]为什么就不做处理了呢??
我一开始也是这么想的,为什么呢??
因为,next[4]的后面的next[5]==(正好)next[4]+1。这不是偶然,因为abca的最大后缀为1(a),而abcab的最大后缀为2(ab),这里的ab包含了前面的a。所以,如果正好next[i]+1=next[i]的话,前面的被后面包含了。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=200003;
char Str[N];
int n,next[N];
void Get_Next(){
next[0]=-1;
int j=-1,i=0;
while(i<n){
if(j==-1||Str[i]==Str[j]){
j++;i++;
next[i]=j;
}
else j=next[j];
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
scanf("%s",Str);
Get_Next();
int ans=n+next[n];
for(int i=0;i<n;i++){
if(next[i]>0&&next[i]+1!=next[i+1])
ans=(ans+next[i])%10007;
}
printf("%d\n",ans);
}
return 0;
}
由此可见,KMP的next数组的博大精深呐!!