SPOJ 1811 LCS - Longest Common Substring

时间:2019-04-19
本文章向大家介绍SPOJ 1811 LCS - Longest Common Substring,主要包括SPOJ 1811 LCS - Longest Common Substring使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

思路

SPOJ 1812 LCS2 - Longest Common Substring II一个思路,改成两个串就有双倍经验了

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int maxlen[502000],suflink[502000],barrel[502000],trans[502000][26],Nodecnt,ranks[502000];
int New_state(int _maxlen,int *_trans,int _suflink){
    ++Nodecnt;
    maxlen[Nodecnt]=_maxlen;
    if(_trans)
        for(int i=0;i<26;i++)
            trans[Nodecnt][i]=_trans[i];
    suflink[Nodecnt]=_suflink;
    return Nodecnt;
}
int add_len(int u,int c){
    int z=New_state(maxlen[u]+1,NULL,0);
    while(u&&trans[u][c]==0){
        trans[u][c]=z;
        u=suflink[u];
    }
    if(!u){
        suflink[z]=1;
        return z;
    }
    int v=trans[u][c];
    if(maxlen[v]==maxlen[u]+1){
        suflink[z]=v;
        return z;
    }
    int y=New_state(maxlen[u]+1,trans[v],suflink[v]);
    suflink[v]=suflink[z]=y;
    while(u&&trans[u][c]==v){
        trans[u][c]=y;
        u=suflink[u];
    }
    return z;
}
void c_sort(int n,int lim){
    memset(barrel,0,sizeof(barrel));
    for(int i=1;i<=n;i++)
        barrel[maxlen[i]]++;
    for(int i=1;i<=lim;i++)
        barrel[i]+=barrel[i-1];
    for(int i=1;i<=n;i++)
        ranks[barrel[maxlen[i]]--]=i;        
}
int mx[502000];  
char s[502000];
int main(){
    // freopen("test.in","r",stdin);
    int cnt=0,last=1;
    Nodecnt=1;
    int len;
    scanf("%s",s+1);
    len=strlen(s+1);
    for(int i=1;i<=len;i++)
        last=add_len(last,s[i]-'a');
    c_sort(Nodecnt,200010);
    scanf("%s",s+1);
    len=strlen(s+1);
    memset(mx,0,sizeof(mx));
    int nowp=1,lent=0;
    for(int i=1;i<=len;i++){
        if(trans[nowp][s[i]-'a']){
            lent++;
            nowp=trans[nowp][s[i]-'a'];
        }
        else{
            while(nowp&&trans[nowp][s[i]-'a']==0)
                nowp=suflink[nowp];
            if(!nowp){
                nowp=1;
                lent=0;
                continue;
            }
            else{
                lent=maxlen[nowp]+1;
                nowp=trans[nowp][s[i]-'a'];
            }
        }
        mx[nowp]=max(mx[nowp],lent);
    }
    for(int i=Nodecnt;i>=1;i--){
        int t=ranks[i];
        mx[suflink[t]]=min(maxlen[suflink[t]],max(mx[suflink[t]],mx[t]));                
    }
    int ans=0;
    for(int i=1;i<=Nodecnt;i++)
        ans=max(mx[i],ans);
    printf("%d\n",ans);
    return 0;
}