求 n 个串的字典序最小的最长公共子串。
和 2 个串的处理方法差不多。
把 n 个串拼接在一起,中间连上一个没有出现过的字符防止匹配过界。
求出 height 数组后二分公共子串长度给后缀数组分组。
然后 check,每一组中是否所有的字符串都包含。
直接遍历 sa 数组,第一个满足的结果就是字典序最小的。
——代码

1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #define N 900005
5 #define M 4001
6
7 int n, len, m, start;
8 int buc[N], x[N], y[N], sa[N], rank[N], height[N], belong[N];
9 char s[N], a[M];
10 bool f[M];
11
12 inline void build_sa()
13 {
14 int i, k, p;
15 for(i = 0; i < m; i++) buc[i] = 0;
16 for(i = 0; i < len; i++) buc[x[i] = s[i]]++;
17 for(i = 1; i < m; i++) buc[i] += buc[i - 1];
18 for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i;
19 for(k = 1; k <= len; k <<= 1)
20 {
21 p = 0;
22 for(i = len - 1; i >= len - k; i--) y[p++] = i;
23 for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
24 for(i = 0; i < m; i++) buc[i] = 0;
25 for(i = 0; i < len; i++) buc[x[y[i]]]++;
26 for(i = 1; i < m; i++) buc[i] += buc[i - 1];
27 for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i];
28 std::swap(x, y);
29 p = 1, x[sa[0]] = 0;
30 for(i = 1; i < len; i++)
31 x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
32 if(p >= len) break;
33 m = p;
34 }
35 }
36
37 inline void build_height()
38 {
39 int i, j, k = 0;
40 for(i = 0; i < len; i++) rank[sa[i]] = i;
41 for(i = 0; i < len; i++)
42 {
43 if(!rank[i]) continue;
44 if(k) k--;
45 j = sa[rank[i] - 1];
46 while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++;
47 height[rank[i]] = k;
48 }
49 }
50
51 inline bool check(int k)
52 {
53 int i, cnt = 1;
54 memset(f, 0, sizeof(f));
55 f[belong[sa[0]]] = 1;
56 for(i = 1; i < len; i++)
57 if(height[i] >= k)
58 {
59 if(!f[belong[sa[i]]]) cnt++;
60 f[belong[sa[i]]] = 1;
61 if(cnt == n)
62 {
63 start = sa[i];
64 return 1;
65 }
66 }
67 else
68 {
69 memset(f, 0, sizeof(f));
70 f[belong[sa[i]]] = 1;
71 cnt = 1;
72 }
73 return 0;
74 }
75
76 int main()
77 {
78 int i, j, l, r, mid, leng;
79 while(scanf("%d", &n) && n)
80 {
81 len = 0;
82 m = 256;
83 memset(belong, 0, sizeof(belong));
84 for(i = 1; i <= n; i++)
85 {
86 scanf("%s", a);
87 for(j = 0; a[j] ^ '\0'; j++) s[len++] = a[j];
88 s[len++] = '#';
89 belong[len] = 1;
90 }
91 len--;
92 build_sa();
93 build_height();
94 for(i = 1; i < len; i++) belong[i] += belong[i - 1];
95 l = 1, r = len, leng = 0, start = -1;
96 while(l <= r)
97 {
98 mid = (l + r) >> 1;
99 if(check(mid)) leng = mid, l = mid + 1;
100 else r = mid - 1;
101 }
102 if(leng && start ^ -1)
103 {
104 for(i = start; i < start + leng; i++) putchar(s[i]);
105 putchar('\n');
106 }
107 else puts("IDENTITY LOST");
108 }
109 return 0;
110 }
来源:https://www.cnblogs.com/zhenghaotian/p/6984603.html
