poj2774 Long Long Message(后缀数组)

只需要把两个串拼接起来,之后求一下后缀数组求可覆盖最长重复子串模板即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=3e5+10;
string a,b;
int id[N],rk[N],sa[N],h[N],cnt[N];
int od[N],px[N];
bool cmp(int x,int y,int w){
    return od[x]==od[y]&&od[x+w]==od[y+w];
}
int main(){
    ios::sync_with_stdio(false);
    cin>>a>>b;
    int sign;
    a=" "+a+"A";
    sign=a.size()-1;
    a+=b;
   // cout<<sign<<endl;
    int i;
    int n=(int)a.size()-1;
    int m=max(n,300);
        for(i=1;i<=n;i++) cnt[rk[i]=a[i]]++;
        for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];
        for(i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
        int p;
        for(int w=1,p=0;w<n;w<<=1,m=p){
            for(p=0,i=n;i>n-w;i--){
                id[++p]=i;
            }
            for(i=1;i<=n;i++){
                if(sa[i]>w){
                    id[++p]=sa[i]-w;
                }
            }
            memset(cnt,0,sizeof cnt);
            for(i=1;i<=n;i++) cnt[px[i]=rk[id[i]]]++;
            for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];
            for(i=n;i>=1;i--) sa[cnt[px[i]]--]=id[i];
            memcpy(od,rk,sizeof rk);
            for(p=0,i=1;i<=n;i++){
                rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
            }
        }
        for(i=1;i<=n;i++){
            if(rk[i]==1)
                continue;
            int x=max(h[rk[i-1]]-1,0);
            while(i+x<=n&&a[i+x]==a[sa[rk[i]-1]+x])
                x++;
            h[rk[i]]=x;
        }
    int ans=0;
    for(i=2;i<=n;i++){
        int x=sa[i-1];
        int y=sa[i];
        if((x<=sign&&y>sign)||(x>sign&&y<=sign)){
            ans=max(ans,h[i]);
        }
    }
    cout<<ans<<endl;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/13303101.html