K - Relevant Phrases of Annihilation
题目大意:给你 n 个串,问你最长的在每个字符串中出现两次且不重叠的子串的长度。
思路:二分长度,然后将height分块,看是否存在一个块里面 每个串都符合条件。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg using namespace std; const int N = 1e5 + ;
const int M = 1e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f; char s[N], str[N];
int n, m, b[N];
int sa[N], t[N], t2[N], c[N], rk[N], height[N];
int L[], R[]; void buildSa(char *s, int n, int m) {
int i, j = , k = , *x = t, *y = t2;
for(i = ; i < m; i++) c[i] = ;
for(i = ; i < n; i++) c[x[i] = s[i]]++;
for(i = ; i < m; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for(int k = ; k <= n; k <<= ) {
int p = ;
for(i = n - k; i < n; i++) y[p++] = i;
for(i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
for(i = ; i < m; i++) c[i] = ;
for(i = ; i < n; i++) c[x[y[i]]]++;
for(i = ; i < m; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = ; x[sa[]] = ;
for(int i = ; i < n; i++) {
if(y[sa[i - ]] == y[sa[i]] && y[sa[i - ] + k] == y[sa[i] + k])
x[sa[i]] = p - ;
else x[sa[i]] = p++;
}
if(p >= n) break;
m = p;
} for(i = ; i < n; i++) rk[sa[i]] = i;
for(i = ; i < n - ; i++) {
if(k) k--;
j = sa[rk[i] - ];
while(s[i + k] == s[j + k]) k++;
height[rk[i]] = k;
}
} bool check(int len, int n) {
int l = , r;
while(l <= n) {
for(int i = ; i <= m; i++) L[i] = inf, R[i] = -inf;
r = l;
L[b[sa[l]]] = min(L[b[sa[l]]], sa[l]);
R[b[sa[l]]] = max(R[b[sa[l]]], sa[l]);
while(r < n && height[r + ] >= len) {
r++;
L[b[sa[r]]] = min(L[b[sa[r]]], sa[r]);
R[b[sa[r]]] = max(R[b[sa[r]]], sa[r]);
} bool flag = true; for(int i = ; i <= m; i++) {
if(L[i] + len > R[i]) {
flag = false;
break;
}
} if(flag) return true;
l = r + ;
}
return false;
} int main() {
int T; scanf("%d", &T);
while(T--) {
scanf("%d", &m); char ch = 'A'; int tot = ;
for(int i = ; i <= m; i++) {
scanf("%s", str);
int len = strlen(str);
for(int j = ; j < len; j++) {
s[tot] = str[j];
b[tot++] = i;
}
s[tot++] = ch++;
}
s[tot] = '\0'; buildSa(s, tot + , ); int l = , r = tot, mid, ans = ; while(l <= r) {
mid = l + r >> ;
if(check(mid, tot)) ans = mid, l = mid + ;
else r = mid - ;
} printf("%d\n", ans);
}
return ;
} /*
1
4
abbabba
dabddkababa
bacaba
baba
*/