传送门:BZOJ3670
k(n)m(o)p(i)傻逼题。
记num[i]为既是i前缀也是后缀的串的个数,这可以在kmp时一并求出。
然后对于每个i,只要暴力找到最大的j令2*j<=i且j在i意义下既是前缀也是后缀就可以了,这只要一路检测条件然后pre回去,依然是线性的。
代码上的小细节见下。
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int mod=1000000007;
int pre[1000005];
int num[1000005];
char S[1000005];
int n;
void Make_Table(char* S)
{
int len=strlen(S+1);
pre[1]=0;num[1]=1;
int k=0;
for(int i=2;i<=len;i++){
while(k&&S[k+1]!=S[i])
k=pre[k];
if(S[k+1]==S[i])
k++;
pre[i]=k;
num[i]=num[k]+1;
}
}
void GetAns(char* S)
{
long long ans=1;
int len=strlen(S+1),k=0;
for(int i=2;i<=len;i++){
while(k&&S[k+1]!=S[i])
k=pre[k];
if(S[k+1]==S[i])
k++;
while(k&&k*2>i)
k=pre[k];
ans*=(num[k]+1);
ans%=mod;
}
cout<<ans<<endl;
}
void Readdata()
{
freopen("loli.in","r",stdin);
scanf("%d",&n);
}
void Solve()
{
for(int i=1;i<=n;i++){
scanf("%s",S+1);
Make_Table(S);
GetAns(S);
}
}
void Close()
{
fclose(stdin);
fclose(stdout);
}
int main()
{
Readdata();
Solve();
Close();
return 0;
}