后缀自动机(SAM):SPOJ Longest Common Substring II
Longest Common Substring II
Time Limit: 2000ms
Memory Limit: 262144KB
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,然后跑其他字符串,在每一个字符串中,记录SAM节点中每个节点对应的最长长度,最后在所有字符串中SAM的最长长度取MIN,答案最后再在对每个位置的最小值取MAX。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 struct SAM{ 7 int ch[200010][27],len[200010],fa[200010],last,cnt; 8 void Init() 9 { 10 memset(fa,0,sizeof(fa)); 11 last=cnt=1; 12 } 13 void Insert(int c) 14 { 15 int p=last,np=last=++cnt; 16 len[np]=len[p]+1; 17 while(p&&!ch[p][c]) 18 ch[p][c]=np,p=fa[p]; 19 if(!p) 20 fa[np]=1; 21 else{ 22 int q=ch[p][c]; 23 if(len[p]+1==len[q]) 24 fa[np]=q; 25 else{ 26 int nq=++cnt; 27 memcpy(ch[nq],ch[q],sizeof(ch[q])); 28 len[nq]=len[p]+1; 29 fa[nq]=fa[q]; 30 fa[q]=fa[np]=nq; 31 while(p&&ch[p][c]==q) 32 ch[p][c]=nq,p=fa[p]; 33 } 34 } 35 } 36 }sam; 37 char s[100010]; 38 int ans[200010],f[200010]; 39 int main() 40 { 41 memset(ans,127,sizeof(ans)); 42 sam.Init(); 43 scanf("%s",&s); 44 for(int i=0;s[i];i++) 45 sam.Insert(s[i]-'a'); 46 while(~scanf("%s",s)) 47 { 48 memset(f,0,sizeof(f)); 49 int node=1,len=0; 50 for(int i=0;s[i];i++) 51 { 52 int c=s[i]-'a'; 53 while(node&&!sam.ch[node][c]) 54 node=sam.fa[node]; 55 if(!node) 56 node=1,len=0; 57 else 58 len=sam.len[node]+1,node=sam.ch[node][c]; 59 if(len>f[node])f[node]=len; 60 } 61 for(int i=1;i<=sam.cnt;i++) 62 ans[i]=min(ans[i],f[i]); 63 } 64 int ret=0; 65 for(int i=1;i<=sam.cnt;i++) 66 ret=max(ret,ans[i]); 67 printf("%d\n",ret); 68 return 0; 69 }
尽最大的努力,做最好的自己!