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)的主要内容,如果未能解决你的问题,请参考以下文章
SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)两种做法