BZOJ 2946: [Poi2000]公共串
2946: [Poi2000]公共串
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 787 Solved: 342
[Submit][Status][Discuss]
Description
给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l 读入单词
l 计算最长公共子串的长度
l 输出结果
Input
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
Output
仅一行,一个整数,最长公共子串的长度。
Sample Input
3
abcb
bca
acbc
abcb
bca
acbc
Sample Output
2
HINT
Source
求若干字符串的最长公共子串。
和SPOJ的那道题简直一模一样,后缀自动机。
1 #include <bits/stdc++.h> 2 3 const int maxn = 5e5 + 5; 4 5 /* AUTOMATON */ 6 7 int last; 8 int tail; 9 int mini[maxn]; 10 int maxi[maxn]; 11 int step[maxn]; 12 int fail[maxn]; 13 int next[maxn][26]; 14 15 inline void buildAutomaton(char *s) 16 { 17 last = 1; 18 tail = 2; 19 while (*s) 20 { 21 int c = *s++ - 'a'; 22 int p = last; 23 int t = tail++; 24 step[t] = step[p] + 1; 25 mini[t] = maxi[t] = step[t]; 26 while (p && !next[p][c]) 27 next[p][c] = t, p = fail[p]; 28 if (p) 29 { 30 int q = next[p][c]; 31 if (step[q] == step[p] + 1) 32 fail[t] = q; 33 else 34 { 35 int k = tail++; 36 fail[k] = fail[q]; 37 fail[q] = fail[t] = k; 38 step[k] = step[p] + 1; 39 mini[k] = maxi[k] = step[k]; 40 for (int i = 0; i < 26; ++i) 41 next[k][i] = next[q][i]; 42 while (p && next[p][c] == q) 43 next[p][c] = k, p = fail[p]; 44 } 45 } 46 else 47 fail[t] = 1; 48 last = t; 49 } 50 } 51 52 inline void searchAutomaton(char *s) 53 { 54 memset(maxi, 0, sizeof(maxi)); 55 for (int t = 1, k = 0; *s; ) 56 { 57 int c = *s++ - 'a'; 58 if (next[t][c]) 59 ++k, t = next[t][c]; 60 else 61 { 62 while (t && !next[t][c]) 63 t = fail[t]; 64 if (t) 65 k = step[t] + 1, t = next[t][c]; 66 else 67 k = 0, t = 1; 68 } 69 if (maxi[t] < k) 70 maxi[t] = k; 71 } 72 for (int i = tail - 1; i; --i) 73 if (maxi[fail[i]] < maxi[i]) 74 maxi[fail[i]] = maxi[i]; 75 for (int i = 1; i < tail; ++i) 76 if (mini[i] > maxi[i]) 77 mini[i] = maxi[i]; 78 } 79 80 inline int calculateAutomaton(void) 81 { 82 register int ret = 0; 83 for (int i = 1; i < tail; ++i) 84 if (ret < mini[i]) 85 ret = mini[i]; 86 return ret; 87 } 88 89 /* MAIN FUNC */ 90 91 char str[maxn]; 92 93 signed main(void) 94 { 95 int n; 96 scanf("%d", &n); 97 scanf("%s", str); 98 buildAutomaton(str); 99 for (int i = 1; i < n; ++i) 100 scanf("%s", str), searchAutomaton(str); 101 printf("%d\n", calculateAutomaton()); 102 }
@Author: YouSiki