Topic Link: UVA 11107-life Forms
Title: Given n strings, the longest string is a substring of N/2 string.
Problem-solving ideas: suffix array, after processing the suffix array, the binary length, each traversal of the height array, when the length is insufficient to segment, if there is a section containing N/2 starting point, then the feasible length.
#include <cstdio> #include <cstring> #include <set> #include <algorithm> using namespace std;
const int maxlen = 200005;
struct Suffix_arr {int n, S[maxlen];
int Tmp_one[maxlen], Tmp_two[maxlen], C[maxlen];
int Sa[maxlen], Rank[maxlen], Height[maxlen];
void Init ();
void Build_arr (int m);
void Get_height ();
}suf;
int N, MaxLen, Id[maxlen];
void Init () {maxlen = 0;
Suf.init ();
Char word[1005];
for (int i = 0; i < N; i++) {scanf ("%s", word);
if (N = = 1) {printf ("%s\n", word);
Return
} int len = strlen (word);
MaxLen = Max (MaxLen, Len);
for (int j = 0; J < Len; J + +) {ID[SUF.N] = i;
suf.s[suf.n++] = Word[j];
} suf.s[suf.n++] = ' Z ' + i + 1;
} suf.build_arr (' Z ' + N + 1);
Suf.get_height ();
} bool Judge (int l, int flag) {set<int> vis;
Vis.insert (Id[suf.sa[0]); For (int i = 1; i < SUF.N;
i++) {while (I < SUF.N && Suf.height[i] >= l) Vis.insert (id[suf.sa[i++]]);
if (Vis.size () * 2 > N) {if (flag) return true;
for (int j = 0; J < L; j + +) printf ("%c", Suf.s[suf.sa[i-1] + j]);
printf ("\ n");
} vis.clear ();
Vis.insert (Id[suf.sa[i]);
} return false;
} void Solve () {if (N = = 1) return;
if (!judge (1, 1)) {printf ("? \ n");
Return
} int L = 1, r = maxlen + 1;
while (L < r) {int mid = (L + r)/2;
if (Judge (Mid, 1)) L = mid + 1;
else R = Mid;
} judge (L-1, 0);
} int main () {int cas = 0;
while (scanf ("%d", &n) = = 1 && N) {if (cas++) printf ("\ n");
Init ();
Solve ();
} return 0;
} void Suffix_arr::init () {n = 0;} void Suffix_arR::get_height () {for (int i = 0; i < n; i++) rank[sa[i]] = i;
int k = 0;
for (int i = 0; i < n; i++) {if (k) k--;
if (rank[i] = = 0) continue;
Int j = Sa[rank[i]-1];
while (s[i+k] = = S[j+k]) k++;
Height[rank[i]] = k;
}} void Suffix_arr::build_arr (int m) {int *x = Tmp_one, *y = Tmp_two;
for (int i = 0; i < m; i++) c[i] = 0;
for (int i = 0; i < n; i++) c[x[i] = s[i]]++;
for (int i = 1; i < m; i++) c[i] + = c[i-1];
for (int i = n-1; I >= 0; i--) sa[--c[x[i]] = i;
for (int k = 1; k <= N; k <<= 1) {int mv = 0;
for (int i = n-k; i < n; i++) y[mv++] = i;
for (int i = 0; i < n; i++) if (Sa[i] >= k) {y[mv++] = sa[i]-K;
} for (int i = 0; i < m; i++) c[i] = 0;
for (int i = 0; i < n; i++) c[x[y[i]]]++;
for (int i = 1; i < m; i++) c[i] + = c[i-1]; for (int i = n-1;; = 0;
i--) sa[--c[x[y[i]] [y[i];
Swap (x, y); MV = 1;
X[sa[0]] = 0; for (int i = 1; i < n; i++) x[sa[i]] = (y[sa[i-1] [= Y[sa[i]] && y[sa[i-1] + K] = = Y[sa[i] + K]?
Mv-1: mv++);
if (MV >= N) break;
m = mv; }
}