poj2774 sa模版

学习地址:http://blog.csdn.net/yxuanwkeith/article/details/50636898

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=400010;
char s[maxn],s1[maxn],s2[maxn];
int ans,tax[maxn],tp[maxn],sa[maxn],ra[maxn],H[maxn],n,m;
void rsort(){
    for(int i=0;i<=m;++i)tax[i]=0;
    for(int i=1;i<=n;++i)tax[ra[tp[i]]]++;
    for(int i=1;i<=m;++i)tax[i]+=tax[i-1];
    for(int i=n;i>=1;--i)sa[tax[ra[tp[i]]]--]=tp[i];
}
int cmp(int x,int y,int w){return tp[x]==tp[y]&&tp[x+w]==tp[y+w];}
void pre(){
    for(int i=1;i<=n;++i)ra[i]=s[i]-'a'+1,tp[i]=i;
    m=32;rsort();
    for(int w=1,p=1,i;p<n;w+=w,m=p){
    //p==n是说明已经得到各个后缀之间的大小关系,故可跳出循环
    //并且最后p一定能==n因为各个后缀长度不一样,一定能排出一个序; 
        for(p=0,i=n-w+1;i<=n;++i)tp[++p]=i;
        for(i=1;i<=n;++i)if(sa[i]>w)tp[++p]=sa[i]-w;
        rsort();swap(ra,tp);ra[sa[1]]=p=1;
    //这里换一下才方便由这一次的ra得到下一次的ra; 
        for(i=2;i<=n;++i)ra[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
    }
    int j,k=0;
    for(int i=1;i<=n;H[ra[i++]]=k)
        for(k=k?k-1:k,j=sa[ra[i]-1];s[i+k]==s[j+k];++k);
}
int main(){
    scanf("%s%s",s1+1,s2+1);
    int len1=strlen(s1+1),len2=strlen(s2+1);
    for(int i=1;i<=len1;++i)s[i]=s1[i];
    s[len1+1]='a'+30;
    for(int i=1;i<=len2;++i)s[i+len1+1]=s2[i];
    n=len1+len2+1;
    pre();ans=0;
    //for(int i=1;i<=n;++i)cout<<sa[i]<<' '<<H[i]<<endl;
    for(int i=2;i<=n;++i){
        if((sa[i-1]<=len1)!=(sa[i]<=len1)&&ans<H[i])ans=H[i];
    }
    cout<<ans;
    system("pause");
    return 0;
}
/*
yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother
*/
原文地址:https://www.cnblogs.com/dibaotianxing/p/8196504.html