spoj1812 LCS2 - Longest Common Substring II
Posted weeping
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spoj1812 LCS2 - Longest Common Substring II相关的知识,希望对你有一定的参考价值。
地址:http://www.spoj.com/problems/LCS2/
题面:
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
Notice: new testcases added
思路:
对第一个穿构建sam,然后让后面的串在sam上走,同时记录每个串跑完后各个状态的所能匹配的最长长度,然后对所有串取个最小值,之后再取个最大值。
注意:如果状态p能够到达,那么状态fa[p]也必然能够到达,但可能在匹配时不会走到fa[p]状态,所以当p可达时,要更新fa[p]。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 struct SAM 6 { 7 static const int MAXN = 100001<<1;//大小为字符串长度两倍 8 static const int LetterSize = 26; 9 10 int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN]; 11 int sum[MAXN], tp[MAXN]; //用于拓扑排序,tp为排序后的数组 12 13 void init( void) 14 { 15 last = tot = 1; 16 len[1] = 0; 17 memset(ch,0,sizeof ch); 18 memset(fa,0,sizeof fa); 19 } 20 21 void add( int x) 22 { 23 int p = last, np = last = ++tot; 24 len[np] = len[p] + 1; 25 while( p && !ch[p][x]) ch[p][x] = np, p = fa[p]; 26 if( p == 0) 27 fa[np] = 1; 28 else 29 { 30 int q = ch[p][x]; 31 if( len[q] == len[p] + 1) 32 fa[np] = q; 33 else 34 { 35 int nq = ++tot; 36 memcpy( ch[nq], ch[q], sizeof ch[q]); 37 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq; 38 while( p && ch[p][x] == q) ch[p][x] = nq, p = fa[p]; 39 } 40 } 41 } 42 43 void toposort( void) 44 { 45 for(int i = 1; i <= len[last]; i++) sum[i] = 0; 46 for(int i = 1; i <= tot; i++) sum[len[i]]++; 47 for(int i = 1; i <= len[last]; i++) sum[i] += sum[i-1]; 48 for(int i = 1; i <= tot; i++) tp[sum[len[i]]--] = i; 49 } 50 } sam; 51 char ss[100004]; 52 int ans,mx[100001<<1],mi[100001<<1]; 53 54 int main(void) 55 { 56 //freopen("in.acm","r",stdin); 57 sam.init(); 58 scanf("%s",ss); 59 for(int i=0,len=strlen(ss);i<len;i++) sam.add(ss[i]-‘a‘); 60 for(int i=1;i<=sam.tot;i++) mi[i]=1e6; 61 sam.toposort(); 62 while(~scanf("%s",ss)) 63 { 64 for(int i=0,len=strlen(ss),p=1,cnt=0;i<len;i++) 65 { 66 int c=ss[i]-‘a‘; 67 if(sam.ch[p][c]) 68 p=sam.ch[p][c],cnt++; 69 else 70 { 71 while(p&&!sam.ch[p][c]) p=sam.fa[p]; 72 if(!p) 73 p=1,cnt=0; 74 else 75 cnt=sam.len[p]+1,p=sam.ch[p][c]; 76 } 77 mx[p]=max(mx[p],cnt); 78 } 79 for(int i=sam.tot;i;i--) 80 { 81 int p=sam.tp[i]; 82 mi[p]=min(mx[p],mi[p]); 83 if(mx[p]&&sam.fa[p]) mx[sam.fa[p]]=sam.len[sam.fa[p]]; 84 mx[p]=0; 85 } 86 } 87 for(int i=1;i<=sam.tot;i++) ans=max(ans,mi[i]); 88 printf("%d\n",ans); 89 return 0; 90 }
以上是关于spoj1812 LCS2 - Longest Common Substring II的主要内容,如果未能解决你的问题,请参考以下文章
spoj 1812 LCS2 - Longest Common Substring II (后缀自己主动机)
[SPOJ1812-LCS2]Longest Common Substring II
SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)两种做法