牛客 动物园 (KMP)
题意:给一个字符串求num数组的乘积,num数组是前缀与后缀相同的个数,且前后缀不相交的个数;
题解:求KMP,易得长度为i的字符串不能由nex[i]>i/2的位置转移,且明显有单调性,所以我们可以从后,用类似并查集路径压缩的方式修改nex数组与num数组,并时间约为O(n)。
#include<iostream>
#include<cstring>
using namespace std;
const int N=1000007;
const int mod=1e9+7;
int t,nex[N],f[N];
char s[N];
int fin(int p,int k){
if(nex[p]>k){
int to=fin(nex[p],k);
f[p]=f[to]+1;
nex[p]=to;
return to;
}
else{
return nex[p];
}
}
void kmp(){
int l=0,r=1,len=strlen(s);
nex[l]=-1;
f[l]=-1;
while(r<len){
if(l==-1||s[l]==s[r]){
l++;
r++;
nex[r]=l;
f[r]=f[l]+1;
}
else{
l=nex[l];
}
}
for(int i=len;i>=1;i--){
if(nex[i]>i/2){
int to=fin(nex[i],i/2);
f[i]=f[to]+1;
nex[i]=to;
}
}
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%s",s);
kmp();
long long ans=1;
int len=strlen(s);
for(int i=1;i<=len;i++){
ans=ans*(f[i]+1)%mod;
}
cout<<ans<<"
";
}
}