AcWing 1000. 动物园
原题链接
简单
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=1e6+10,M=1e9+7;
char s[N];
int ne[N],cnt[N];//cnt[i]存放从[1,i]区间所有前面等于后面的子串数(包括自己本身)
int main()
{
int n;
cin>>n;
while(n--)
{
cin>>s+1;
int len=strlen(s+1);
//求next,cnt数组
cnt[1]=1;//只有第一个字符时cnt为1(自己本身)
for(int i=2,j=0;i<=len;i++)
{
while(j && s[i]!=s[j+1]) j=ne[j];
if(s[i]==s[j+1]) j++;
ne[i]=j;
cnt[i]=cnt[ne[i]]+1;//加一就是加上自己本身
}
//匹配过程
LL ans=1; //要用long long型存储答案否则会溢出
for(int i=1,j=0;i<=len;i++)
{
//照样进行kmp匹配,不断向前推进匹配j
while(j && s[i]!=s[j+1]) j=ne[j];
if(s[i]==s[j+1]) j++;
//当j不符合要求(前缀等于后缀的子串会发生重叠)就根据next数组后退到ne[j]
while(j && j>i/2) j=ne[j];
//对于整个字符串s不重叠的所有前缀等于后缀的子串数量
//就等于退到刚符合要求(不会发生重叠的最大子串位置)的j时的cnt[j]数(该子串[1,j]中的所有前面等于后面包括自己的子串数量)
ans=ans*((LL)cnt[j]+1)%M; //根据题目计算连乘的num+1,其中num就等于cnt
}
cout<<ans%M<<endl; //保证取余输出答案
}
return 0;
}