题目链接:[NOI2014] 动物园
维护一个border 树,然后对于每个点,继承父亲的答案,暴力向下跳即可。
因为由于border树的性质,跳到的全是当前点的border
为了方便向下跳,我们维护一个根节点到当前节点的节点栈
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
int n,q,fail[N],res[N],ans; char str[N];
vector<int> g[N],v;
void dfs(int x,int fa){
res[x]=res[fa];
while(res[x]<v.size()-1&&v[res[x]+1]*2<=x) res[x]++;
for(int to:g[x]){
v.push_back(to);
dfs(to,x);
v.pop_back();
}
}
void solve(){
scanf("%s",str+1); n=strlen(str+1); ans=1;
for(int i=2,j=0;i<=n;i++){
while(j&&str[i]!=str[j+1]) j=fail[j];
if(str[i]==str[j+1]) j++;
fail[i]=j;
}
for(int i=0;i<=n;i++) g[i].clear();
for(int i=1;i<=n;i++) g[fail[i]].push_back(i);
dfs(0,0);
for(int i=2;i<=n;i++) ans=1LL*ans*(res[i]+1)%mod;
printf("%d\n",ans);
}
signed main(){
v.push_back(0);
int T; cin>>T; while(T--) solve();
return 0;
}