P2375 [NOI2014] 动物园

不难发现,这道题的 \(num\) 数组是一个求和的过程,看一下下面这张 \(copy\) 的图:

P2375 [NOI2014] 动物园_#include

也就是说对于 \(num[i]\)\(num[next[i]]\)(弱化 \(num\):可重叠),所有的 \(num[next[i]]\) ,$ num[i]$ 都可以有,并且在原来的基础上 \(add \ 1\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + 5;
const int P = 1e9 + 7;
char s[maxn];
int nxt[maxn],num[maxn];
int n,T;
long long ans;
void clear(){
	memset(nxt,0,sizeof nxt);
	memset(num,0,sizeof num);
	return ;
}
void make_nxt(){
	for(int i=2,j=0;i<=n;i++){
		while(j>0 && s[i]!=s[j+1])j=nxt[j];
		if(s[i]==s[j+1])j++;
		nxt[i]=j;num[i]=num[j]+1;
	}
}
void make_num(){
	for(int i=2,j=0;i<=n;i++){
		while(j>0 && s[i]!=s[j+1])j=nxt[j];
		if(s[i]==s[j+1])j++;
		while((j<<1)>i)j=nxt[j];
		ans=(ans*(long long)(num[j]+1))%P;
	}
}
int main(){
	scanf("%d",&T);
	while(T--){
		clear();ans=1;num[1]=1;
		scanf("%s",s+1);
		n=strlen(s+1);
		make_nxt();
		make_num();
		printf("%lld\n",ans);
	}
	return 0;
}