zoukankan      html  css  js  c++  java
  • BZOJ 4755:[Jsoi2016]扭动的回文串

    题解:

    先求每个串的最长回文串

    然后两个串的一定是一个串的某一个最长回文串向两边扩展

    用后缀数组求

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int maxn=800009;
    
    int n,len;
    int ans=0;
    
    char A[maxn];
    int Atl[maxn],Atr[maxn];
    char B[maxn];
    int Btl[maxn],Btr[maxn];
    
    
    char s[maxn];
    int c[maxn],sa[maxn];
    int t1[maxn],t2[maxn];
    void BuildSA(int n,int m){
        int *x=t1,*y=t2;
        for(int i=1;i<=m;++i)c[i]=0;
        for(int i=1;i<=n;++i)c[x[i]=s[i]]++;
        for(int i=2;i<=m;++i)c[i]+=c[i-1];
        for(int i=n;i>=1;--i)sa[c[x[i]]--]=i;
        
        for(int k=1;k<n;k<<=1){
            int p=0;
            for(int i=n-k+1;i<=n;++i)y[++p]=i;
            for(int i=1;i<=n;++i)if(sa[i]>k)y[++p]=sa[i]-k;
            
            for(int i=1;i<=m;++i)c[i]=0;
            for(int i=1;i<=n;++i)c[x[y[i]]]++;
            for(int i=2;i<=m;++i)c[i]+=c[i-1];
            for(int i=n;i>=1;--i)sa[c[x[y[i]]]--]=y[i];
            
            swap(x,y);
            x[sa[1]]=p=1;
            for(int i=2;i<=n;++i){
                int a=sa[i],b=sa[i-1];
                if((y[a]==y[b])&&(y[a+k]==y[b+k]))x[sa[i]]=p;
                else x[sa[i]]=++p;
            }
            if(p>=n)break;
            m=p;
        }
    }
    int rk[maxn],ht[maxn];
    void GetHeight(int n){
        for(int i=1;i<=n;++i)rk[sa[i]]=i;
        int k=0;
        for(int i=1;i<=n;++i){
            if(k)k--;
            if(rk[i]==1)continue;
            int j=sa[rk[i]-1];
            while(s[i+k]==s[j+k])++k;
            ht[rk[i]]=k;
        }
    }
    int f[maxn][20];
    void STinit(int n){
        for(int i=1;i<=n;++i)f[i][0]=ht[i];
        for(int j=1;j<=19;++j){
            for(int i=1;i+(1<<j)-1<=n;++i){
                f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    int ds[maxn];
    int Querymin(int l,int r){
        int k=ds[r-l+1];
        return min(f[l][k],f[r-(1<<k)+1][k]);
    }
    
    
    int main(){
        scanf("%d",&n);
        scanf("%s",A+1);
        s[len=1]='*';
        for(int i=1;i<=n;++i){
            s[++len]=A[i];s[++len]='*';
        }
        for(int i=1;i<=n*2+1;++i)A[i]=s[i];
        scanf("%s",B+1);
        s[len=1]='*';
        for(int i=1;i<=n;++i){
            s[++len]=B[i];s[++len]='*';
        }
        for(int i=1;i<=n*2+1;++i)B[i]=s[i];
        n=n*2+1;
        
        for(int i=1;i<=n+n;++i)ds[i]=(int)log2(i+0.5);
        
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;++i)s[i]=s[n*2-i+1]=A[i];
        BuildSA(n+n,200);
        GetHeight(n+n);
        STinit(n+n);
        for(int i=1;i<=n;++i){
            int x=i,y=2*n-i+1;
            x=rk[x];y=rk[y];
            if(x>y)swap(x,y);
            len=Querymin(x+1,y);
            Atl[i]=i-len+1;
            Atr[i]=i+len-1;
            ans=max(ans,len*2-1);
        }
        
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;++i)s[i]=s[n*2-i+1]=B[i];
        BuildSA(n+n,200);
        GetHeight(n+n);
        STinit(n+n);
        for(int i=1;i<=n;++i){
            int x=i,y=2*n-i+1;
            x=rk[x];y=rk[y];
            if(x>y)swap(x,y);
            len=Querymin(x+1,y);
            len=min(len,min(i,n-i+1));
            Btl[i]=i-len+1;
            Btr[i]=i+len-1;
            ans=max(ans,len*2-1);
        }
        
        for(int i=1;i<=n;++i)s[n-i+1]=A[i];
        for(int i=1;i<=n;++i)s[i+n]=B[i];
        BuildSA(n+n,200);
        GetHeight(n+n);
        STinit(n+n);
        
    //    cout<<(A+1)<<endl;
    //    cout<<(B+1)<<endl;
    //    cout<<(s+1)<<endl;
        for(int i=1;i<=n;++i){
            int l=Atl[i],r=Atr[i];
            if((l==1)||(r==n))continue;
            int x=n-l+2,y=r+n-1;
            x=rk[x];y=rk[y];
            if(x>y)swap(x,y);
            len=Querymin(x+1,y);
            len=min(len,min(l,n-r+2));
            ans=max(ans,len*2+(r-l+1));
        }
        
        for(int i=1;i<=n;++i){
            int l=Btl[i],r=Btr[i];
            if((l==1)||(r==n))continue;
            int x=n-l,y=r+n+1;
            x=rk[x];y=rk[y];
            if(x>y)swap(x,y);
            len=Querymin(x+1,y);
            len=min(len,min(l+1,n-r));
            ans=max(ans,len*2+(r-l+1));    
        }
        cout<<ans/2<<endl;
        return 0;
    }
  • 相关阅读:
    io学习
    asp.net文件上传进度条研究
    asp.net页面中的Console.WriteLine结果如何查看
    谨慎跟随初始目的不被关联问题带偏
    android 按钮特效 波纹 Android button effects ripple
    安卓工作室 日志设置
    安卓工作室 文件浏览器 android studio File browser
    一个新的Android Studio 2.3.3可以在稳定的频道中使用。A new Android Studio 2.3.3 is available in the stable channel.
    新巴巴运动网上商城 项目 快速搭建 教程 The new babar sports online mall project quickly builds a tutorial
    码云,git使用 教程-便签
  • 原文地址:https://www.cnblogs.com/zzyer/p/8647776.html
Copyright © 2011-2022 走看看