SPOJ LCS2 1812. Longest Common Substring II

SPOJ Problem Set (classical)

1812. Longest Common Substring II

Problem code: LCS2

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

Notice: new testcases added


Added by: Bin Jin
Date: 2007-09-24
Time limit: 2s
Source limit: 50000B
Memory limit: 256MB
Cluster: Pyramid (Intel Pentium III 733 MHz)
Languages: All except: C++ 4.0.0-8

第一个串建SAM,剩下的串在上面跑....记录下每个节点的最小匹配长度(初始值是 len 即能表示的最长后缀),

从后向前更新fa节点的LCS....

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=110000;

struct SAM_Node
{
    SAM_Node *fa,*next[26];
    int len,id,pos;
    SAM_Node(){}
    SAM_Node(int _len)
    {
        fa=0; len=_len;
        memset(next,0,sizeof(next));
    }
};

SAM_Node SAM_node[maxn*2],*SAM_root,*SAM_last;
int SAM_size;

SAM_Node *newSAM_Node(int len)
{
    SAM_node[SAM_size]=SAM_Node(len);
    SAM_node[SAM_size].id=SAM_size;
    return &SAM_node[SAM_size++];
}

SAM_Node *newSAM_Node(SAM_Node *p)
{
    SAM_node[SAM_size]=*p;
    SAM_node[SAM_size].id=SAM_size;
    return &SAM_node[SAM_size++];
}

void SAM_init()
{
    SAM_size=0;
    SAM_root=SAM_last=newSAM_Node(0);
    SAM_node[0].pos=0;
}

void SAM_add(int x,int len)
{
    SAM_Node *p=SAM_last,*np=newSAM_Node(p->len+1);
    np->pos=len; SAM_last=np;
    for(;p&&!p->next[x];p=p->fa)
        p->next[x]=np;
    if(!p)
    {
        np->fa=SAM_root;
        return ;
    }
    SAM_Node *q=p->next[x];
    if(q->len==p->len+1)
    {
        np->fa=q;
        return ;
    }
    SAM_Node *nq=newSAM_Node(q);
    nq->len=p->len+1;
    q->fa=nq; np->fa=nq;
    for(;p&&p->next[x]==q;p=p->fa)
        p->next[x]=nq;
}

char str[maxn],other[maxn];
int LCS[maxn*2],len,n;
int c[maxn*2]; SAM_Node *top[maxn*2];

int main()
{
    scanf("%s",str);
    len=strlen(str);
    SAM_init();
    for(int i=0;i<len;i++)
        SAM_add(str[i]-'a',i+1);

    for(int i=0;i<SAM_size;i++)
        c[SAM_node[i].len]++;
    for(int i=1;i<=len;i++)
        c[i]+=c[i-1];
    for(int i=0;i<SAM_size;i++)
        top[--c[SAM_node[i].len]]=&SAM_node[i];

    while(scanf("%s",other)!=EOF)
    {
        n++;
        int len2=strlen(other);
        SAM_Node* now=SAM_root;
        int temp=0;
        for(int i=0;i<len2;i++)
        {
            int x=other[i]-'a';
            if(now->next[x])
            {
                temp++;
                now=now->next[x];
            }
            else
            {
                while(now&&now->next[x]==0)
                    now=now->fa;
                if(now)
                {
                    temp=now->len+1;
                    now=now->next[x];
                }
                else
                {
                    temp=0;
                    now=SAM_root;
                }
            }
            if(temp>LCS[now->id])
                LCS[now->id]=temp;
        }
        for(int i=SAM_size-1;i>=0;i--)
        {
            if(LCS[top[i]->id]<top[i]->len)
                top[i]->len=LCS[top[i]->id];
            if(top[i]->fa&&LCS[top[i]->fa->id]<LCS[top[i]->id])
               LCS[top[i]->fa->id]=LCS[top[i]->id];
            LCS[top[i]->id]=0;
        }
    }
    int ans=0;
    for(int i=1;i<SAM_size;i++)
    {
        if(ans<SAM_node[i].len)
            ans=SAM_node[i].len;
    }
    printf("%d\n",ans);
    return 0;
}

SPOJ LCS2 1812. Longest Common Substring II

时间: 2025-01-15 05:56:34

SPOJ LCS2 1812. Longest Common Substring II的相关文章

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

http://www.spoj.com/problems/LCS2/ 发现了我原来对sam的理解的一个坑233 本题容易看出就是将所有匹配长度记录在状态上然后取min后再对所有状态取max. 但是不要忘记了一点:更新parent树的祖先. 为什么呢?首先如果子树被匹配过了,那么长度一定大于任意祖先匹配的长度(甚至有些祖先匹配长度为0!为什么呢,因为我们在匹配的过程中,只是找到一个子串,可能还遗漏了祖先没有匹配到,这样导致了祖先的记录值为0,那么在对对应状态去min的时候会取到0,这样就wa了.而

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

[题目链接] http://www.spoj.com/problems/LCS2/ [题目大意] 求n个串的最长公共子串 [题解] 对一个串建立后缀自动机,剩余的串在上面跑,保存匹配每个状态的最小值, 取最小值中的最大值即可.由于跑的地方只记录了匹配结尾的状态, 所以还需要更新parent树上的状态,既然匹配到了子节点, 那么parent树链上的值就都能够取到l, 一开始给每个不同状态按照l从小到大分配储存地址, 这样,我们就可以从匹配长度最长的开始更新parent树的情况. [代码] #inc

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.每次匹配完一个字符串的时候,

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

spoj 1812 LCS2 - Longest Common Substring II 题意: 给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串. 限制: 1 <= n <= 10 |A[i]| <= 1e5 思路: 和spoj 1811 LCS差不多的做法 把其中一个A建后缀自动机 考虑一个状态s, 如果A之外的其他串对它的匹配长度分别是a[1], a[2], ..., a[n - 1], 那么min(a[1], a[2], ..., a[n - 1]

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

spoj 1812 LCS2 - Longest Common Substring II 题意: 给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串. 限制: 1 <= n <= 10 |A[i]| <= 1e5 思路: 和spoj 1811 LCS几乎相同的做法 把当中一个A建后缀自己主动机 考虑一个状态s, 假设A之外的其它串对它的匹配长度各自是a[1], a[2], ..., a[n - 1], 那么min(a[1], a[2], ..., a[n -

spoj1812 LCS2 - Longest Common Substring II

地址:http://www.spoj.com/problems/LCS2/ 题面: LCS2 - Longest Common Substring II no tags 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 cons

SPOJ Longest Common Substring II

Longest Common Substring II Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: LCS264-bit integer IO format: %lld      Java class name: Main A string is finite sequence of characters over a non-empty finite se

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

[SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记录\(f[i]\)表示走到了\(i\)节点 能够匹配上的最长公共子串的长度 当然,每个串的\(f[i]\)可以更新\(f[i.parent]\) 所以需要拓扑排序 对于每个串求出每个节点的最长匹配 然后对他们取\(min\),表示某个节点大家都能匹配的最长长度 最后对于所有点的值都取个\(max\)

【SPOJ】Longest Common Substring II

[SPOJ]Longest Common Substring II 多个字符串求最长公共子串 还是将一个子串建SAM,其他字符串全部跑一边,记录每个点的最大贡献 由于是所有串,要对每个点每个字符串跑完后去最小值才是每个点的最终贡献 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm