刷题SPOJ 1812 LCS2 - Longest Common Substring II

Posted hongyj

tags:

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

A string is finite sequence of characters over a non-empty finite set Σ.

In this problem, Σ is the set of lowercase letters.

Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.

Here common substring means a substring of two or more strings.

Input

The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.

Output

The length of the longest common substring. If such string doesn‘t exist, print "0" instead.

Example

Input:
alsdfkjfjkdsal
fdjskalajfkdsla
aaaajfaaaa

Output:
2

Solution

提出一个串做SAM
做完后,将剩下的所有串与SAM进行匹配
每次匹配时记录每个节点以它为结尾最长能够匹配多长,然后将这次匹配的结果与保存的最后的答案取min(我们要保证剩下的所有的串与第一个串匹配的是同一段)
全部匹配完后在每个节点取max就是答案了

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=10+5,MAXS=100000+10,inf=0x3f3f3f3f;
int n,las=1,tot=1,len[MAXS<<1],fa[MAXS<<1],ch[MAXS<<1][30],ans,st[MAXS<<1],rk[MAXS<<1],cnt[MAXS],now[MAXS<<1];
char s[MAXN][MAXS];
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char ch='')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(ch!='')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void extend(int c)
{
    int p=las,np=++tot;
    las=np;
    len[np]=len[p]+1;
    while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
    if(!p)fa[np]=1;
    else
    {
        int q=ch[p][c];
        if(len[q]==len[p]+1)fa[np]=q;
        else
        {
            int nq=++tot;
            fa[nq]=fa[q];
            memcpy(ch[nq],ch[q],sizeof(ch[nq]));
            len[nq]=len[p]+1,fa[np]=fa[q]=nq;
            while(p&&ch[p][c]==q)ch[p][c]=nq,p=fa[p];
        }
    }
}
inline int match(int w)
{
    memset(now,0,sizeof(now));
    for(register int i=1,j=1,res=0,lt=strlen(s[w]+1);i<=lt;++i)
    {
        int c=s[w][i]-'a'+1;
        if(ch[j][c])res++,j=ch[j][c];
        else
        {
            while(j&&!ch[j][c])j=fa[j];
            if(!j)res=0,j=1;
            else res=len[j]+1,j=ch[j][c];
        }
        chkmax(now[j],res);
    }
    for(register int i=tot;i>=1;--i)chkmax(now[fa[rk[i]]],now[rk[i]]);
    for(register int i=1;i<=tot;++i)chkmin(st[i],now[i]);
}
int main()
{
    while(scanf("%s",s[++n]+1)!=EOF);
    n--;
    for(register int i=1,lt=strlen(s[1]+1);i<=lt;++i)extend(s[1][i]-'a'+1);
    for(register int i=1;i<=tot;++i)st[i]=len[i];
    for(register int i=1;i<=tot;++i)cnt[len[i]]++;
    for(register int i=1,lt=strlen(s[1]+1);i<=lt;++i)cnt[i]+=cnt[i-1];
    for(register int i=1;i<=tot;++i)rk[cnt[len[i]]--]=i;
    for(register int i=2;i<=n;++i)match(i);
    for(register int i=2;i<=tot;++i)chkmax(ans,st[i]);
    write(ans,'
');
    return 0;
}

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

SPOJ1812 LCS2

spoj1812 LCS2 - Longest Common Substring II

SPOJ 1812 LCS2

SPOJ 1812 LCS2 后缀自动机

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

并不对劲的[spoj1812]LCS2