• bzoj3145:[Feyat cup 1.5]Str


    mdzz

    题解很简单:

    钦定一对(i,j)可以不相等,贡献就是lcp(i+1,j+1)+lcs(i-1,j-1)

    套路地

    按照hei对lcp也就是height进行合并

    最大化lcs

    set启发式合并

    错误点:

    1.sa写错

    2.a=fin(a),并查集也能写错

    3.ST表(i+(1<<j)-1)<=n

    **

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template <class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar())) (ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template <class T>il void prt(T a[],int st,int nd){
        for(reg i=st;i<=nd;++i) cout<<a[i]<<" ";cout<<endl;
    }
    namespace Miracle{
    const int N=2e5+40000;
    char A[N],B[N];
    int n,m;
    int lg[N];
    struct SASA{
        char s[N];
        int id[N];
        int xx[N],yy[N];
        int buc[N],sa[N],rk[N];
        int hei[N];
        int f[N][20];
        int n;
        void build(){
            int m=130;
            int *x=xx,*y=yy;
            for(reg i=1;i<=n;++i) ++buc[x[i]=s[i]];
            for(reg i=1;i<=m;++i) buc[i]+=buc[i-1];
            for(reg i=1;i<=n;++i) sa[buc[x[i]]--]=i;
            for(reg k=1;k<=n;k<<=1){
                int num=0;
                for(reg i=n-k+1;i<=n;++i) y[++num]=i;
                for(reg i=1;i<=n;++i){
                    if(sa[i]>k) y[++num]=sa[i]-k;
                }
                for(reg i=1;i<=m;++i) buc[i]=0;
                for(reg i=1;i<=n;++i) ++buc[x[i]];
                for(reg i=1;i<=m;++i) buc[i]+=buc[i-1];
                for(reg i=n;i>=1;--i) sa[buc[x[y[i]]]--]=y[i],y[i]=0;
                swap(x,y);
                num=1;
                x[sa[1]]=1;
                for(reg i=2;i<=n;++i){
                    x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])?num:++num;
                }
                if(num==n) break;
                m=num;
            }
            
            for(reg i=1;i<=n;++i) rk[sa[i]]=i;
            for(reg k=0,i=1;i<=n;++i){
                if(k)--k;
                if(rk[i]==1) continue;
                int j=sa[rk[i]-1];
                while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k]) ++k;
                hei[rk[i]]=k;
            }
            
            for(reg i=1;i<=n;++i) f[i][0]=hei[i];
            for(reg j=1;j<=17;++j){
                for(reg i=1;(i+(1<<j)-1)<=n;++i){
                    f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
                }
            }
            
            //cout<<"string ";cout<<s+1<<endl;
            //cout<<" sa ";prt(sa,1,n);
            //cout<<" rk ";prt(rk,1,n);
            //cout<<" hei ";prt(hei,1,n);
        }
        int lcp(int x,int y){
            //cout<<" calc lcp "<<x<<" "<<y<<endl;
            if(x==y) return n-x+1;
            x=rk[x],y=rk[y];
            if(x>y) swap(x,y);
            ++x;
            int len=lg[y-x+1];
            int ret=min(f[x][len],f[y-(1<<len)+1][len]);
            //cout<<" retlcp "<<ret<<endl;
            return ret;
        }
    }str[2];
    
    int rev(int x){
        return x>n?n+(n+m)-x+1:n-x+1;
    }
    struct po{
        int x;
        po(){}
        po(int xx){
            x=xx;
        }
        bool friend operator <(po a,po b){
            int ta=rev(a.x);
            int tb=rev(b.x);
            return str[1].rk[ta]<str[1].rk[tb];
        }
    };
    int fa[N];
    
    int id[N];
    bool cmp(int x,int y){
        return str[0].hei[x]>str[0].hei[y];
    }
    
    set<po>s[N][2];
    int ans;
    
    int fin(int x){
        return fa[x]==x?x:fa[x]=fin(fa[x]);
    }
    void merge(int a,int b,int l){
        //cout<<" merge ----------"<<a<<" "<<b<<" "<<l<<endl;
        //cout<<" sz a "<<s[a][0].size()<<" "<<s[a][1].size()<<endl;
        //cout<<" sz b "<<s[b][0].size()<<" "<<s[b][1].size()<<endl;
        a=fin(a),b=fin(b);
        fa[b]=a;
        
        
        if(s[a][0].size()+s[a][1].size()<s[b][0].size()+s[b][1].size()) s[a][0].swap(s[b][0]),s[a][1].swap(s[b][1]);
        
        if(s[a][1].size()){
            for(solid y:s[b][0]){
                auto bc=s[a][1].upper_bound(y);
                if(bc!=s[a][1].end()){
                    ans=max(ans,1+l+str[1].lcp(rev(y.x),rev((*bc).x)));
                }
                if(bc!=s[a][1].begin()){
                    --bc;
                    ans=max(ans,1+l+str[1].lcp(rev(y.x),rev((*bc).x)));
                }
            }
        }
        if(s[a][0].size()){
            for(solid y:s[b][1]){
                //cout<<" twotowto "<<y.x<<endl;
                auto bc=s[a][0].upper_bound(y);
                if(bc!=s[a][0].end()){
                //    cout<<" bac "<<(*bc).x<<endl;
                    ans=max(ans,1+l+str[1].lcp(rev(y.x),rev((*bc).x)));
                }
                if(bc!=s[a][0].begin()){
                    --bc;
                //    cout<<" pre "<<(*bc).x<<endl;
                    ans=max(ans,1+l+str[1].lcp(rev(y.x),rev((*bc).x)));
                }
            }
        }
        for(solid y:s[b][0]) s[a][0].insert(y);
        for(solid y:s[b][1]) s[a][1].insert(y);
        
        //cout<<" after ans "<<ans<<endl;
        
    }
    int main(){
        scanf("%s",A+1);n=strlen(A+1);
        scanf("%s",B+1);m=strlen(B+1);
        
        lg[0]=0;
        for(reg i=1;i<=n+m+3;++i){
            lg[i]=(i>>(lg[i-1]+1))?lg[i-1]+1:lg[i-1];
        }
        
        for(reg i=2;i<=n;++i){
            str[0].s[++str[0].n]=A[i];
            //id[str[0].n]=1;
        }
        str[0].s[++str[0].n]='A';
        for(reg i=2;i<=m;++i){
            str[0].s[++str[0].n]=B[i];
            //id[str[0].n]=2;
        }
        str[0].s[++str[0].n]='B';
        
        reverse(A+1,A+n+1);
        reverse(B+1,B+m+1);
        
        for(reg i=2;i<=n;++i){
            str[1].s[++str[1].n]=A[i];
            //id[str[1].n]=1;
        }
        str[1].s[++str[1].n]='A';
        for(reg i=2;i<=m;++i){
            str[1].s[++str[1].n]=B[i];
            //id[str[1].n]=2;
        }
        str[1].s[++str[1].n]='B';
        
        str[0].build();
        str[1].build();
        
        
        for(reg i=1;i<=str[0].n;++i){
            fa[i]=i;
            id[i]=i;
            if(i<=n){
                s[i][0].insert(po(i));
            }else{
                s[i][1].insert(po(i));
            }
        }
        sort(id+1,id+str[0].n+1,cmp);
        
        
        
        for(reg i=1;i<=str[0].n;++i){
            int x=id[i];
            if(x==1) continue;
            merge(str[0].sa[x],str[0].sa[x-1],str[0].hei[x]);
        }
        printf("%d",ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
  • 相关阅读:
    linux的ls命令输出结果的逐条解释
    dubbo用途介绍
    dubbo有什么作用
    来自19岁女孩和软件开发人员的建议
    C++的反思[转]
    mysql各种引擎对比、实战
    俗话:MySQL索引
    Mysql 30条军规
    MySQL事务原理&实战【官方精译】
    php-msf 源码解读【转】
  • 原文地址:https://www.cnblogs.com/Miracevin/p/11140840.html
Copyright © 2020-2023  润新知