uoj219

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zxin__/article/details/80552350

明天就是thuscDay1,发现好久没写过SA模板了。正好以前没做过这题,那就钦定你来练手了。
然后模板题都敲错了:
1.query时没判询问下标是否真实存在于区间 [ 1 , n ]
2.求height数组时没有判下标<=n
25->55->80->100,感觉要是当时NOI赛场上,这样会血崩的。
明天要是有这种暴力95的题,我绝不写正解,除非只差这题就**了。
不知道为何跑不过二分哈希。

#include<bits/stdc++.h>
inline int Min(const int&a,const int&b){return a<b?a:b;}
const int N=30005;
char ibuf[1<<19],*ih=ibuf;
int T,n,i,j,x,y;
char c[N];
int lo[N],s1[N],s2[N];
struct SA{
    int rk[N],z[18][N];
    inline void build(char*c){
        static int sa[N],f[N],g[N];
        int p=0,i,j;memset(f,0,104);
        for(i=1;i<=n;++i)++f[c[i]-'a'];
        for(i=1;i<26;++i)f[i]+=f[i-1];
        for(i=1;i<=n;++i)sa[f[c[i]-'a']--]=i;
        for(i=1;i<=n;++i)rk[sa[i]]=p+=c[sa[i]]!=c[sa[i-1]];
        for(i=1;p<n;i<<=1){
            static int a[N],b[N],z[N];
            memset(f,0,(p+1)<<2);
            for(j=1;j<=n;++j){
                a[j]=rk[j],b[j]=j+i<=n?rk[j+i]:0;
                ++f[b[j]];
            }
            for(j=p-1;j>=0;--j)f[j]+=f[j+1];
            for(j=1;j<=n;++j)z[f[b[j]]--]=j;
            memset(f,0,(p+1)<<2);
            for(j=1;j<=n;++j)++f[a[j]];
            for(j=1;j<=p;++j)f[j]+=f[j-1];
            for(j=1;j<=n;++j)sa[f[a[z[j]]]--]=z[j];p=0;
            for(j=1;j<=n;++j)rk[sa[j]]=p+=a[sa[j]]>a[sa[j-1]] || b[sa[j]]>b[sa[j-1]];
        }
        for(i=1,j=0;i<=n;z[0][rk[i++]]=j){
            for(j?--j:0;i+j<=n && sa[rk[i]+1]+j<=n && c[i+j]==c[sa[rk[i]+1]+j];++j);
            if(rk[i]==n)j=0;
        }
        for(i=1;1<<i<=n;++i)
            for(j=1;j<=n-(1<<i)+1;++j)z[i][j]=Min(z[i-1][j],z[i-1][j+(1<<(i-1))]);
    }
    int query(int x,int y){
        if(y>n)return 0;
        x=rk[x];y=rk[y];if(x>y){int t=x;x=y;y=t;}--y;
        int l=lo[y-x+1];
        return Min(z[l][x],z[l][y-(1<<l)+1]);
    }
}a,b;
int main(){
    //freopen("excellent1.in","r",stdin);
    for(i=2;i<N-1;++i)lo[i+1]=lo[i]+!(i&(i-1));
    scanf("%d",&T);fread(ibuf,1,1<<19,stdin);
    while(T--){
        while(isspace(*ih))++ih;
        for(n=1;!isspace(*ih);c[n++]=*ih++);c[n--]=0;
        a.build(c);std::reverse(c+1,c+n+1);b.build(c);
        memset(s1+1,0,n<<2);memset(s2+1,0,n<<2);
        for(i=1;i<<1<=n;++i)
            for(j=i;j+i<=n;j+=i){
                y=Min(a.query(j+1,j+i+1),i-1);x=Min(b.query(n-j+1,n-j-i+1),i);
                if(x+y>=i){
                    ++s1[j-x+1];--s1[j+y-i+2];
                    ++s2[j+i-x+i];--s2[j+i+y+1];
                }
            }
        for(i=1;i<=n;++i)s1[i]+=s1[i-1],s2[i]+=s2[i-1];
        long long ans=0;
        for(i=1;i<n;++i)ans+=1ll*s2[i]*s1[i+1];
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxin__/article/details/80552350