[NOI2014] 动物园
试题分析
首先一定与kmp数组有关。
然后求出每个位置最长的题目要求的数组num。
然后考虑这两个数组怎么统计。
由于num前缀与后缀一样,那么只需要统计前i个的前缀等于后缀无要求的数量。
这个东西我们可以直接从前后缀递推出来。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define LL long long
inline int read(){
int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int INF = 2147483600;
const int MAXN = 2000010;
const LL Mod = 1000000007;
int nxt[MAXN+1],cnt[MAXN+1],num[MAXN+1];
char str[MAXN+1]; int T;
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
T=read();
while(T--){
memset(num,0,sizeof(num));
memset(nxt,0,sizeof(nxt)); nxt[0]=-1; num[0]=-1;
LL ans=1;
scanf("%s",str+1); int len=strlen(str+1);
for(int i=1;i<=len;i++){
int j=i-1,k=i-1; while(j>-1){
if(str[i]==str[nxt[j]+1]) {nxt[i]=nxt[j]+1; break;}
else j=nxt[j];
} cnt[i]=cnt[nxt[i]]+1;
while(k>-1){
if(str[i]==str[num[k]+1]) {num[i]=num[k]+1; break;}
else k=num[k];
} while(num[i]>(i>>1)) num[i]=nxt[num[i]];
ans=1LL*ans*(cnt[num[i]]+1)%Mod;
} printf("%lld
",ans);
}
return 0;
}