这道题本来是用来练习KMP的
结果貌似一个next数组就可以解决
首先 对于每一个元字符串的前缀数组来说 至少会有一个与他匹配的 (其实就是他本身)
那么 再看看next数组的含义 每一个不为0的next数就代表着有一个子串重复过一次 比如abab 的next数组为0001
b所在的1 就代表着长度为1 的原字符串的前缀数组重复过一个 即a重复了一次 这时 我们会发现 ab也重复过一次 那么这一次与去哪了呢? 这时 我们需要在abab的后面加一个不相干的字符 ‘ * ’, 这样 abab* 的next数组就变成了
00012 这样ab的重复的次数就出现了 在我们之后的统计的过程中 我们可以让所有在next数组中大于0的数使sum++;
然后再让sum+strlen(字符串) 就可以得出总的重复数了 别忘了模上10007
下面是AC 代码
# include <stdio.h>
# include <string.h>
char s[200000+10];
//char p[200000+10];
int sum;
int f[200000+10];
void next(int x){
f[0]=f[1]=0;
for(int i=1;i<x-1;i++){
int j = f[i];
while(j&&s[i]!=s[j]) j=f[j];
f[i+1] = s[i]==s[j]?j+1:0;
}
}
void solve(int x){
for(int i=0;i<x;i++){;
if(f[i]>0)
sum+=1;
//printf("%d \n",f[i]);
}
}
int main(){
int T;
while(scanf("%d",&T)!=EOF){
int len;
memset(f,0,sizeof(f));
scanf("%d",&len);
scanf("%s",s);
sum=0;
s[len]='*';
s[len+1]='\0';
next(len+1);
solve(len+1);
printf("%d\n",(sum+len)%10007);
}
return 0;
}