题解 P2375 【[NOI2014]动物园】
思路
先用裸的\(KMP\)求出\(fail(next)\)数组(随便叫的无所谓啦)和不管重叠时的数量记为\(ans_{i}\),\(ans\)的定义类似于\(fail(next)\),然后再跑一遍,求出\(<=\frac{i}{2}\)的数量,可结合代码理解
Code
#include<bits/stdc++.h>
using namespace std;
int n,l,fail[1000010],j,ans[1000010];
long long ANS,mod=1000000007;
char s[1000010];
int main()
{
scanf("%d",&n);
while(n--)
{
ANS=1;
ans[1]=1;
scanf("%s",s+1);
l=strlen(s+1);
j=0;
for(int i=2;i<=l;i++)
{
while(j&&s[j+1]!=s[i])
{
j=fail[j];
}
if(s[j+1]==s[i])
{
fail[i]=++j;
}
else
{
fail[i]=0;
}
ans[i]=ans[j]+1;
}
j=0;
for(int i=2;i<=l;i++)
{
while(j&&s[j+1]!=s[i])
{
j=fail[j];
}
j+=(s[j+1]==s[i]);
while(j*2>i)
{
j=fail[j];
}
ANS=ANS*(ans[j]+1)%mod;
}
cout<<ANS<<endl;
}
}