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;
}

 

posted @ 2019-07-05 21:18  *Miracle*  阅读(180)  评论(0编辑  收藏  举报