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;
    }
  • 相关阅读:
    Start Python 学习笔记(琐碎知识,持续更新。。。)
    电子商务网站数据分析常用指标(转)
    设计模式学习笔记——适配器(Adapter)模式
    Json概述以及python对json的相关操作
    数据层参考资料
    Oracle内存组件与进程的相关知识总结
    面试题_二分查找及其变形
    两路归并的数组和链表实现
    Mysq性能分析 —— Genral log(普通日志)与 Slow log(慢速日式)
    设计模式学习笔记——工厂方法模式
  • 原文地址:https://www.cnblogs.com/zzyer/p/8647776.html
Copyright © 2011-2022 走看看