spoj Longest Common Substring II

Longest Common Substring II

 SPOJ - LCS2 

求10个串的LCS

/*
    1、用第一个串建立后缀自动机
    2、len[s] 表示状态s 所能代表的字符串的最大长度
      mx[s] 表示状态s 在 当前匹配的串的最长匹配后缀长度
      ans[s] 表示状态s 在所有串的最长匹配后缀长度
    3、用第2——第10个串在后缀自动机上跑,每次mx[s]=max(mx[s],当前匹配长度)
      每一个串跑完之后,更新 ans[s]=min(ans[s],mx[s])
    4、每次匹配完一个字符串的时候,要 从后缀自动机 parent 树 上的叶子节点 向根更新,
      因为后缀自动机的parent树上,min[s]=max(fa[s])+1,所以子节点能匹配的长度 比 父节点的max要长。父节点是子节点的后缀,父节点可以匹配子节点的后max(fa[s])位,但是在那串在后缀自动机上跑的时候,不能保证经过 s 的 时候 也经过了s到根的链。所以只要子节点s 有匹配长度,父节点的mx[fa[s]]即可修改为len[fa[s]]即max(fa[s])
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010
using namespace std;
char s[maxn];
int len[maxn<<1],ch[maxn<<1][26],fa[maxn<<1],sz=1,last=1,p,q,np,nq;
int c[maxn],sa[maxn<<1],mx[maxn<<1],ans[maxn<<1];
void Insert(int c){
    np=++sz;
    len[np]=len[last]+1;
    ans[sz]=len[sz];
    p=last;
    while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
    if(!p)fa[np]=1;
    else {
        q=ch[p][c];
        if(len[q]==len[p]+1)fa[np]=q;
        else {
            nq=++sz;
            memcpy(ch[nq],ch[q],sizeof(ch[q]));
            fa[nq]=fa[q];
            fa[q]=fa[np]=nq;
            ans[nq]=len[nq]=len[p]+1;
            while(ch[p][c]==q)ch[p][c]=nq,p=fa[p];
        }
    }
    last=np;
}
void solve(){
    int l,c,now,nowlen,x;
    while(scanf("%s",s+1)!=EOF){
        l=strlen(s+1);
        now=1;nowlen=0;
        for(int i=1;i<=l;i++){
            c=s[i]-'a';
            while(now&&!ch[now][c]){
                now=fa[now];
                nowlen=len[now];
            }
            if(!now){
                nowlen=0;
                now=1;
            }
            else if(ch[now][c]){
                nowlen++;
                now=ch[now][c];
            }
            mx[now]=max(mx[now],nowlen);
        }
        for(int i=sz;i;i--){
            x=sa[i];
            ans[x]=min(ans[x],mx[x]);
            if(fa[x]&&mx[x])mx[fa[x]]=len[fa[x]];
            mx[x]=0;
        }
    }
    int Ans=0;
    for(int i=1;i<=sz;i++)Ans=max(Ans,ans[i]);
    printf("%d",Ans);
}
int main(){
    freopen("Cola.txt","r",stdin);
    scanf("%s",s+1);
    int l=strlen(s+1);
    for(int i=1;i<=l;i++)Insert(s[i]-'a');
    for(int i=1;i<=sz;i++)c[len[i]]++;
    for(int i=1;i<=l;i++)c[i]+=c[i-1];
    for(int i=sz;i;i--)sa[c[len[i]]--]=i;
    solve();
    return 0;
}

 

posted @ 2018-04-10 15:03  Echo宝贝儿  阅读(178)  评论(0编辑  收藏  举报