题意:求一个字符串所有的前缀在这个字符串中出现的次数之和。
思路1:kmp把两个串拼接起来。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500005;
const int mod = 10007;
char str[maxn],str2[maxn];
int f[maxn];
typedef long long LL;
LL cnt[maxn];
void get_fail( char* P,int *f ){
f[0] = -1;cnt[0] = 1;
int m = strlen(P);
for( int i = 1;i < m;i++ ){
int j = f[i-1];
while( j != -1 && P[j+1]!=P[i] )j = f[j];
cnt[i] = 1;
if( P[j+1]==P[i] ) f[i] = j+1;
else f[i] = -1;
if( f[i] != -1 ) cnt[i] = (cnt[i] +cnt[ f[i] ])%mod;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;scanf("%d",&n);
scanf("%s",str);
int len = strlen(str);
strcpy( str2,str );
strcat( str,str2 );
get_fail(str,f);
long long ans = 0;
int p ;
for( int i = len;i < 2*len;i++ ){
if( i == len ){
p = f[i];
while( p!= -1 && (p >= len || i-p < len) ) p = f[p];
if( p!=-1 ) ans += cnt[p],ans%=mod;
}else{
while( p != -1 && str[p+1] != str[i] ) p = f[p];
if( str[p+1] == str[i] ) p++;
if( p != -1 ) {
ans += cnt[p];
ans %= mod;
}
}
}
printf("%lld\n",ans);
}
return 0;
}
思路2:
裸的扩展kmp