spoj 1812 LCS2(SAM+DP)

Posted

tags:

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

 

 
Time Limit: 236MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu

Description

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

【题意】

 

  求若干个串的最长公共子串。

 

【思路】

 

       SAM+DP

       先拿个串建个SAM,然后用后面的串匹配,SAM中每个结点维护两个信息:mx表示与当前串匹配到该结点的最大长度,mn表示与前几个串匹配到该结点的最小长度。最后ans取所有节点mn的最大值。

       注意mn[p]初始化为l[p]

       cxlove:出现次数向父亲传递,接收串数从儿子获取

 

【代码】

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 const int N = 5*1e5+10;
 6 
 7 char s[N];
 8 int sz,last,root,l[N],ch[N][26],fa[N],mn[N],mx[N];
 9 int b[N],cnt[N];
10 void add(int x) {
11     int c=s[x]-a;
12     int p=last,np=++sz; last=np; 
13     l[np]=mn[np]=x+1;
14     for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
15     if(!p) fa[np]=root;
16     else {
17         int q=ch[p][c];
18         if(l[p]+1==l[q]) fa[np]=q;
19         else {
20             int nq=++sz; l[nq]=mn[nq]=l[p]+1;
21             memcpy(ch[nq],ch[q],sizeof(ch[q]));
22             fa[nq]=fa[q];
23             fa[np]=fa[q]=nq;
24             for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
25         }
26     }
27 }
28 
29 int main() {
30     root=last=++sz;
31     scanf("%s",s);
32     int len=strlen(s);
33     for(int i=0;i<len;i++) add(i);
34     for(int i=1;i<=sz;i++) cnt[l[i]]++;
35     for(int i=1;i<=len;i++) cnt[i]+=cnt[i-1];
36     for(int i=1;i<=sz;i++) b[cnt[l[i]]--]=i;
37     while(scanf("%s",s)==1) {
38         int p=root; len=0;
39         for(int i=0;s[i];i++) {
40             int c=s[i]-a;
41             if(ch[p][c]) { len++; p=ch[p][c]; }
42             else {
43                 while(p&&!ch[p][c]) p=fa[p];
44                 if(!p) { len=0; p=root; }
45                 else { len=l[p]+1; p=ch[p][c]; }
46             }
47             if(len>mx[p]) mx[p]=len;
48         }
49         for(int i=sz;i;i--) {
50             p=b[i];
51             if(mx[p]<mn[p]) mn[p]=mx[p];
52             if(fa[p] && mx[fa[p]]<mx[p]) mx[fa[p]]=mx[p];
53             mx[p]=0;
54         }
55     }
56     int ans=0;
57     for(int i=1;i<=sz;i++)
58         if(mn[i]>ans) ans=mn[i];
59     printf("%d",ans);
60     return 0;
61 }

 

以上是关于spoj 1812 LCS2(SAM+DP)的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ1812 LCS2

SPOJ 1812 LCS2 [后缀自动机]

SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)两种做法

spoj1812 LCS2 - Longest Common Substring II

LCS&LCS2 SAM SPOJ

SPOJ 1812 LCS2