记录编号 408555 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2016]优秀的拆分 最终得分 100
用户昵称 GravatarrpCardinal 是否通过 通过
代码语言 C++ 运行时间 0.310 s
提交时间 2017-05-24 21:52:14 内存使用 33.28 MiB
显示代码纯文本
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 30000
#define LOG4N 17
using namespace std;

#ifdef _WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif

int n,l2[4*MAXN+10],f[MAXN+10],g[MAXN+10];
char s[MAXN+10];

struct SuffixTree {
    int ch[2*MAXN+10][26],f[2*MAXN+10],a[2*MAXN+10],b[MAXN+10],n,m,last,u[2*MAXN+10],v[2*MAXN+10],p[2*MAXN+10],me,idx,e[4*MAXN+10],pos[2*MAXN+10],mi[LOG4N+1][4*MAXN+10];
    SuffixTree() {memset(ch,-1,sizeof(ch));}
    void clear() {
        memset(ch,-1,sizeof(ch[0])*(m+1));
        m=last=n=0; f[0]=-1;
    }
    void addChar(int k) {
        int p=last,np=++m; a[np]=a[p]+1; last=np; b[++n]=np;
        while (p!=-1&&ch[p][k]==-1) {ch[p][k]=np; p=f[p];}
        if (p==-1) f[np]=0;
        else {
            int q=ch[p][k];
            if (a[q]==a[p]+1) f[np]=q;
            else {
                int nq=++m; a[nq]=a[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[nq]));
                f[nq]=f[q]; f[q]=nq; f[np]=nq;
                while (p!=-1&&ch[p][k]==q) {ch[p][k]=nq; p=f[p];}
            }
        }
    }
    void addEdge(int x,int y) {
        ++me; v[me]=y; p[me]=u[x]; u[x]=me;
    }
    void dfs(int x) {
        e[++idx]=x; pos[x]=idx;
        for (int i=u[x];i;i=p[i]) {
            dfs(v[i]); e[++idx]=x;
        }
    }
    void buildTree() {
        memset(u,0,sizeof(int)*(m+1)); me=0;
        for (int i=1;i<=m;++i) addEdge(f[i],i);
        idx=0; dfs(0);
        for (int i=1;i<=idx;++i) mi[0][i]=a[e[i]];
        for (int j=0;j<LOG4N;++j)
            for (int i=1;i<=idx;++i)
                mi[j+1][i]=min(mi[j][i],mi[j][i+(1<<j)]);
        l2[0]=0; for (int i=1;i<=idx;++i) l2[i]=l2[i-1]+(i>>l2[i-1]>>1);
    }
    int lcp(int x,int y) {
        x=pos[b[x]]; y=pos[b[y]];
        if (x>y) swap(x,y); int d=l2[y-x];
        return min(mi[d][x],mi[d][y-(1<<d)+1]);
    }
}T1,T2;

int main() {
    freopen("excellent.in","r",stdin);
    freopen("excellent.out","w",stdout);
    int T; scanf("%d",&T);
    while (T--) {
        scanf("%s",s+1); n=strlen(s+1);
        T1.clear(); for (int i=1;i<=n;++i) T1.addChar(s[i]-'a');
        T1.buildTree();
        T2.clear(); for (int i=n;i;--i) T2.addChar(s[i]-'a');
        T2.buildTree();
        memset(f,0,sizeof(int)*(n+2));
        memset(g,0,sizeof(int)*(n+2));
        for (int d=1;d+d<=n;++d)
            for (int i=d;i+d<=n;i+=d) {
                int x=min(d,T1.lcp(i,i+d)),y=min(d-1,T2.lcp(n-i,n-i-d));
                if (x+y>=d) {
                    ++f[i+d-x+d]; --f[i+d+y+1];
                    ++g[i+1+y-d]; --g[i-x];
                }
            }
        for (int i=1;i<=n;++i) f[i]+=f[i-1];
        for (int i=n;i;--i) g[i]+=g[i+1];
        long long ans=0;
        for (int i=1;i<=n;++i) ans+=1ll*f[i]*g[i+1];
        printf(lld "\n",ans);
    }
    fclose(stdin); fclose(stdout);
    return 0;
}