求一个字符串的不同前缀在自身串中出现的次数,用扩展kmp,自己匹配自己。
求出next数组后,把next中各项相加就是答案,假设next[i] = k,那么可知s[i,…,i+k-1] == s[0,…,k-1]
所以以i为起点的后面的字串可以匹配k个前缀
#include <cstdio>
#include <algorithm>
const int mod = 10007;
int t,m,next[202020],ans ;
char s[202020];
void getEK(){
next[0] = m;
int j = 0;
while(j+1<m && s[j] == s[j+1]) j++;
next[1] = j;
int k = 1;
for(int i = 2;i<m;i++){
int p = next[k] + k -1;
int L = next[i-k];
if(i + L <p+1) next[i] = L;
else {
j = std::max(0,p-i+1);
while(i+j<m && s[i+j] == s[j]) j++;
next[i] = j;
k = i;
}
}
}
int main(){
scanf("%d",&t);
while(t--){
ans = 0;
scanf("%d",&m);
scanf("%s",s);
getEK();
for(int i = 0;i<m;i++){
ans += next[i];
ans %= mod;
}
printf("%d\n",ans);
}
return 0;
}