SPOJ 1812 Longest Common Substring II

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ 1812 Longest Common Substring II相关的知识,希望对你有一定的参考价值。

http://www.spoj.com/problems/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<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

#define N 100002

char s[N];

int tot=1,len[N<<1],ch[N<<1][26],fa[N<<1];
int last,p,q,np,nq;

int c[N],sa[N<<1];

int mx[N<<1],ans[N<<1];

void extend(int c)
{
    len[np=++tot]=len[last]+1;
    ans[tot]=len[tot];
    for(p=last;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
    if(!p) fa[np]=1;
    else
    {
        q=ch[p][c];
        if(len[q]==len[p]+1) fa[np]=q;
        else
        {
            nq=++tot;
            memcpy(ch[nq],ch[q],sizeof(ch[q]));
            fa[nq]=fa[q];
            fa[q]=fa[np]=nq;
            len[nq]=len[p]+1;
            for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
        }
    }
    last=np;
}

void build()
{
    scanf("%s",s+1);
    int L=strlen(s+1);
    for(int i=1;i<=L;++i) extend(s[i]-a);
    for(int i=1;i<=tot;++i) c[len[i]]++;
    for(int i=1;i<=L;++i) c[i]+=c[i-1];
    for(int i=tot;i;--i) sa[c[len[i]]--]=i;
}

void solve()
{
    int L,c,now,now_len;
    int x;
    while(scanf("%s",s+1)!=EOF)
    {
        L=strlen(s+1);
        now=1;
        for(int i=1;i<=L;++i)
        {
            c=s[i]-a;
            while(now && !ch[now][c]) 
            {
                now=fa[now];
                now_len=len[now];
            }
            if(!now)
            {
                now_len=0;
                now=1;
            }
            else if(ch[now][c])
            {
                now_len++;
                now=ch[now][c];
            }
            mx[now]=max(mx[now],now_len);
        }
        for(int i=tot;i;--i)
        {
            x=sa[i];
            ans[x]=min(ans[x],mx[x]);
            if(fa[p] && mx[x]) mx[fa[p]]=min(mx[fa[p]],mx[x]);
            mx[x]=0;
        }
    }
    int out=0;
    for(int i=1;i<=tot;++i) out=max(out,ans[i]);
    printf("%d",out);
}

int main()
{
    build();
    solve();
    return 0;
}

 

以上是关于SPOJ 1812 Longest Common Substring II的主要内容,如果未能解决你的问题,请参考以下文章

spoj1812 LCS2 - Longest Common Substring II

刷题SPOJ 1812 LCS2 - Longest Common Substring II

SPOJ 1812 Longest Common Substring II

SPOJ 1812 Longest Common Substring II(后缀自动机)

spoj 1812 LCS2 - Longest Common Substring II (后缀自己主动机)

[SPOJ1812-LCS2]Longest Common Substring II