牛客 动物园 (KMP)

牛客 动物园 (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<<"\n";
	}
}
posted @ 2021-03-26 23:18  ccsu_madoka  阅读(64)  评论(0编辑  收藏  举报