用奇怪的字符把它们连接起来。然后求sa,hei,二分答案,按mid分组。
判断每一组存在的后缀属于的原串的种类数是不是存在那么多个。
这个做法可以推广到多串求LCS,然后多个log,完美在SPOJ上T掉。
Code
1 /** 2 * poj 3 * Problem#3294 4 * Accepted 5 * Time: 391ms 6 * Memory: 5024k 7 */ 8 #include <iostream> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cstdio> 12 #ifndef WIN32 13 #define Auto "%lld" 14 #else 15 #define Auto "%I64d" 16 #endif 17 using namespace std; 18 typedef bool boolean; 19 #define ll long long 20 21 #define pii pair<int, int> 22 #define fi first 23 #define sc second 24 25 const int N = 1e5 + 105, M = 105; 26 27 typedef class Pair3 { 28 public: 29 int x, y, id; 30 31 Pair3() { } 32 Pair3(int x, int y, int id):x(x), y(y), id(id) { } 33 }Pair3; 34 35 typedef class SuffixArray { 36 protected: 37 Pair3 T1[N], T2[N]; 38 int cnt[N]; 39 40 public: 41 int n; 42 char *str; 43 int sa[N], rk[N], hei[N]; 44 45 void set(int n, char* str) { 46 this->n = n; 47 this->str = str; 48 memset(sa, 0, sizeof(sa)); 49 memset(rk, 0, sizeof(rk)); 50 memset(hei, 0, sizeof(hei)); 51 } 52 53 void radix_sort(Pair3* x, Pair3* y) { 54 int m = max(n, 256); 55 memset(cnt, 0, sizeof(int) * m); 56 for (int i = 0; i < n; i++) 57 cnt[x[i].y]++; 58 for (int i = 1; i < m; i++) 59 cnt[i] += cnt[i - 1]; 60 for (int i = 0; i < n; i++) 61 y[--cnt[x[i].y]] = x[i]; 62 63 memset(cnt, 0, sizeof(int) * m); 64 for (int i = 0; i < n; i++) 65 cnt[y[i].x]++; 66 for (int i = 1; i < m; i++) 67 cnt[i] += cnt[i - 1]; 68 for (int i = n - 1; ~i; i--) 69 x[--cnt[y[i].x]] = y[i]; 70 } 71 72 void build() { 73 for (int i = 0; i < n; i++) 74 rk[i] = str[i]; 75 for (int k = 1; k < n; k <<= 1) { 76 for (int i = 0; i + k < n; i++) 77 T1[i] = Pair3(rk[i], rk[i + k], i); 78 for (int i = n - k; i < n; i++) 79 T1[i] = Pair3(rk[i], 0, i); 80 radix_sort(T1, T2); 81 int diff = 0; 82 rk[T1[0].id] = 0; 83 for (int i = 1; i < n; i++) 84 rk[T1[i].id] = (T1[i].x == T1[i - 1].x && T1[i].y == T1[i - 1].y) ? (diff) : (++diff); 85 if (diff == n - 1) 86 break; 87 } 88 for (int i = 0; i < n; i++) 89 sa[rk[i]] = i; 90 } 91 92 void get_height() { 93 for (int i = 0, j, k = 0; i < n; i++, (k) ? (k--) : (0)) { 94 if (rk[i]) { 95 j = sa[rk[i] - 1]; 96 while (i + k < n && j + k < n && str[i + k] == str[j + k]) k++; 97 hei[rk[i]] = k; 98 } 99 } 100 } 101 102 const int& operator [] (int p) { 103 return sa[p]; 104 } 105 106 const int& operator () (int p) { 107 return hei[p]; 108 } 109 }SuffixArray; 110 111 int n, m, K; 112 char S[N]; 113 int suf[N]; 114 SuffixArray sa; 115 116 inline boolean init() { 117 scanf("%d", &m); 118 if (!m) 119 return false; 120 K = (m >> 1) + 1; 121 scanf("%s", S); 122 n = strlen(S); 123 for (int i = 1; i < m; i++) { 124 S[n++] = '?'; 125 scanf("%s", S + n); 126 n += strlen(S + n); 127 } 128 suf[n] = 0; 129 for (int i = n - 1; ~i; i--) 130 suf[i] = suf[i + 1] + (S[i] == '?'); 131 sa.set(n, S); 132 return true; 133 } 134 135 int chk_clock = 0; 136 int vis[M]; 137 138 boolean check(int L, int R, int mid) { // [L, R) 139 if (R - L < K) 140 return false; 141 if (suf[sa[L]] - suf[sa[L] + mid]) 142 return false; 143 chk_clock++; 144 int rt = 0; 145 for (int i = L; i < R && rt < K; i++) 146 if (vis[suf[sa[i]]] != chk_clock) 147 vis[suf[sa[i]]] = chk_clock, rt++; 148 return rt >= K; 149 } 150 151 boolean check(int mid) { 152 int lst = 0; 153 boolean rt = false; 154 for (int i = 1; i < n && !rt; i++) 155 if (sa(i) < mid) 156 rt |= check(lst, i, mid), lst = i; 157 if (!rt) 158 rt |= check(lst, n, mid); 159 return rt; 160 } 161 162 void output(int L, int R, int res) { 163 if (!check(L, R, res)) 164 return; 165 for (int i = sa[L], j = 0; j < res; j++) 166 putchar(S[i + j]); 167 putchar(' '); 168 } 169 170 inline void solve() { 171 chk_clock = 0; 172 memset(vis, 0, sizeof(vis)); 173 174 sa.build(); 175 sa.get_height(); 176 177 int l = 1, r = n / m, mid; 178 while (l <= r) { 179 mid = (l + r) >> 1; 180 if (check(mid)) 181 l = mid + 1; 182 else 183 r = mid - 1; 184 } 185 186 if (!(--l)) 187 puts("?"); 188 else { 189 int lst = 0; 190 for (int i = 1; i < n; i++) 191 if (sa(i) < l) 192 output(lst, i, l), lst = i; 193 output(lst, n, l); 194 } 195 puts(""); 196 } 197 198 int main() { 199 while (init()) 200 solve(); 201 return 0; 202 }