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 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