1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| #include <cstdio> #include <cstring> #include <algorithm> using namespace std; template <class Type> void read (Type &x) { char c; bool flag = false; while ((c = getchar()) < '0' || c > '9') c == '-' && (flag = true); x = c - '0'; while ((c = getchar()) >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0'; flag && (x = ~x + 1); } template <class Type, class ...rest> void read (Type &x, rest &...y) { read(x), read(y...); } template <class Type> void write (Type x) { x < 0 && (putchar('-'), x = ~x + 1); x > 9 && (write(x / 10), 0); putchar('0' + x % 10); } void chkmin (int &x, int k) { if (k < x) x = k; } void chkmax (int &x, int k) { if (k > x) x = k; } const int N = 5e5 + 10; char str[N]; int n, m, id[N], sa[N], rnk[N], ht[N], x[N], y[N], c[N], mn[20], mx[20]; void bucsort () { for (int i = 1; i <= m; ++i) c[i] = 0; for (int i = 1; i <= n; ++i) ++c[x[i]]; for (int i = 2; i <= m; ++i) c[i] += c[i - 1]; for (int i = n; i; i--) sa[c[x[y[i]]]--] = y[i]; } void init () { for (int i = 1; i <= n; ++i) x[i] = (str[i] - 'a' + 257) % 128, y[i] = i, sa[i] = 0; bucsort(); for (int k = 1; k <= n; k <<= 1) { int cnt = 0; for (int i = n - k + 1; i <= n; ++i) y[++cnt] = i; for (int i = 1; i <= n; ++i) if (sa[i] > k) y[++cnt] = sa[i] - k; bucsort(); for (int i = 1; i <= n; ++i) y[i] = x[i]; x[sa[1]] = cnt = 1; for (int i = 2; i <= n; ++i) x[sa[i]] = cnt += (y[sa[i]] ^ y[sa[i - 1]] || y[sa[i] + k] ^ y[sa[i - 1] + k]); if ((m = cnt) == n) break; } for (int i = 1; i <= n; ++i) rnk[sa[i]] = i; for (int i = 1, k = 0; i <= n; ++i) { int j = sa[rnk[i] - 1]; if (k) --k; while (i + k <= n && j + k <= n && str[i + k] == str[j + k]) ++k; ht[rnk[i]] = k; } } bool chk (int k, int mid) { bool flag = true; for (int i = 1; i <= k && flag; ++i) if (mx[i] - mn[i] < mid) flag = false; for (int i = 1; i <= k; ++i) mn[i] = n, mx[i] = 0; return flag; } int main () { int T; read(T); while (T--) { n = 0; int k; read(k); for (int i = 1; i <= k; ++i) { scanf("%s", str + n + 1); int t = strlen(str + n + 1); for (int j = n + 1; j <= n + t; ++j) id[j] = i; str[++(n += t)] = 'z' + i; id[n] = 0; } m = 26 + k; init(); int l = 0, r = n >> 1; while (l < r) { int mid = l + r + 1 >> 1; bool flag = false; for (int i = 2; i <= n && !flag; ++i) { if (ht[i] < mid) flag = chk(k, mid); chkmin(mn[id[sa[i]]], sa[i]), chkmax(mx[id[sa[i]]], sa[i]); } chk(k, mid); flag ? l = mid : r = mid - 1; } write(l), puts(""); } return 0; }
|