http://www.lydsy.com/JudgeOnline/problem.php?id=3670

 

法一:KMP+st表

抽离nxt数组,构成一棵树

若nxt[i]=j,则i作为j的子节点

那么num[i] 就是i到根节点的路径上,所有<=i/2 的节点的个数

这棵树的点随深度的递增而增大

所以用st表存这棵树

st 表 开[logn][n],常数优化求st表的过程

#include<cmath>
#include<cstdio>
#include<cstring>

#define N 1000001

using namespace std;

const int mod=1e9+7;

char s[N];
int len;

int f[N];

int dep[N],st[21][N];
int num[N];

void get_next()
{
    int j;
    for(int i=1;i<len;++i)
    {
        j=f[i];
        while(j && s[i]!=s[j]) j=f[j];
        f[i+1]= s[j]==s[i] ? j+1 : 0;
    }
}

void solve()
{
    for(int i=1;i<=len;++i) st[0][i]=f[i],dep[i]=dep[f[i]]+1;
    int lim=1.0*log(len)/log(2);
    for(int j=1;j<=lim;++j) 
        for(int i=1;i<=len;++i)
            st[j][i]=st[j-1][st[j-1][i]];
    int now;
    for(int i=1;i<=len;++i)
    {
        now=i;
        for(int j=lim;j>=0;--j)
            if(st[j][now]*2>i) now=st[j][now];
        num[i]=dep[now]-1;
    }
    int ans=1;
    for(int i=1;i<=len;++i) ans=1LL*ans*(num[i]+1)%mod;
    printf("%d\n",ans);
}

int main()
{
    //freopen("data.in","r",stdin);
    //freopen("my.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        len=strlen(s);
        get_next();
        solve();
    }
}
View Code

相关文章: