NOI2014 动物园

题目连接:戳我

就是......KMP算法的nxt数组表示的是能和它配对的,右端字符最靠右的,字符串的位置。所以我们一个一个向前跳,当此时的j的位置*2小于等于i的时候,就是不重叠的配对子串了。但是一个一个跳跑的有一点慢......所以我们可以上一个倍增数组........

然后开个O2就过去了。。。。

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 1000010
#define MOD 1000000007
#define ull unsigned long long
using namespace std;
int T,len,ans;
int nxt[MAXN],fp[22][MAXN];
char s[MAXN];
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d",&T);
    while(T--)
    {
        ans=1;
        memset(nxt,0,sizeof(nxt));
        scanf("%s",s+1);
        len=strlen(s+1);
        int p=0;
        for(int i=2;i<=len;i++)
        {
            while(p&&s[p+1]!=s[i]) p=nxt[p];
            if(s[p+1]==s[i]) p++;
            nxt[i]=p;
        }
        for(int i=2;i<=len;i++) fp[0][i]=nxt[i];
        for(int k=1;k<=21;k++)
            for(int i=2;i<=len;i++)
                fp[k][i]=fp[k-1][fp[k-1][i]];
        for(int i=2;i<=len;i++)
        {
            int now=i;
            for(int j=21;j>=0;j--)
                if(fp[j][now]*2>i)
                    now=fp[j][now];
            int cur_ans=0;
            for(int j=21;j>=0;j--)
                if(fp[j][now])
                    cur_ans+=(1<<j),now=fp[j][now];
            ans=1ll*ans*(cur_ans+1)%MOD;
        }
        printf("%d
",ans);
    }
    return 0;
}
    
原文地址:https://www.cnblogs.com/fengxunling/p/10756327.html