Description
给定一个字符串,你需要找到一个最长在这个串中至少出现了(k)次的子串
Solution
我们首先对这个串进行后缀排序,那么对于排序后的任意一个区间([l, r]),那么原串中一定有(r - l + 1)个长度为(MIN_{i in (l, r]} {height_i})的相同字串
于是我们就直接把(height)数列扫一边,同时维护一个单调队列,来维护任意相邻的(k - 1)个(height)的最小值,答案便是这些最小值中的最大值
Code
#include <bits/stdc++.h>
using namespace std;
#define fst first
#define snd second
#define mp make_pair
#define squ(x) ((LL)(x) * (x))
#define debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef pair<int, int> pii;
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
inline int read() {
int sum = 0, fg = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
return fg * sum;
}
const int maxn = 2e4 + 10;
const int maxm = 1e6 + 10;
int n, m, k;
int S[maxn], sa[maxn], buc[maxm], rk[maxn], tmp[maxn], height[maxn];
inline void Radix_sort() {
for (int i = 1; i <= m; i++) buc[i] = 0;
for (int i = 1; i <= n; i++) ++buc[rk[i]];
for (int i = 1; i <= m; i++) buc[i] += buc[i - 1];
for (int i = n; i >= 1; i--) sa[buc[rk[tmp[i]]]--] = tmp[i];
}
inline void get_sa() {
for (int i = 1; i <= n; i++) rk[i] = S[i] + 1, tmp[i] = i;
m = 1e6 + 1, Radix_sort();
for (int k = 1; k <= n; k <<= 1) {
int p = 0;
for (int i = n - k + 1; i <= n; i++) tmp[++p] = i;
for (int i = 1; i <= n; i++) if (sa[i] > k) tmp[++p] = sa[i] - k;
Radix_sort(), swap(rk, tmp);
rk[sa[1]] = 1, m = 1;
for (int i = 2; i <= n; i++)
rk[sa[i]] = (tmp[sa[i]] == tmp[sa[i - 1]] && tmp[sa[i] + k] == tmp[sa[i - 1] + k]) ? m : ++m;
if (m >= n) break;
}
}
inline void get_height() {
for (int i = 1, k = 0; i <= n; i++) {
if (k) --k;
int j = sa[rk[i] - 1];
while (S[i + k] == S[j + k]) ++k;
height[rk[i]] = k;
}
}
int main() {
#ifdef xunzhen
freopen("milk.in", "r", stdin);
freopen("milk.out", "w", stdout);
#endif
n = read(), k = read();
for (int i = 1; i <= n; i++) S[i] = read();
get_sa(), get_height();
deque<int> q;
int ans = 0;
for (int i = 2; i <= n; i++) {
while (!q.empty() && height[q.back()] > height[i]) q.pop_back();
q.push_back(i);
while (!q.empty() && q.front() <= i - k + 1) q.pop_front();
chkmax(ans, height[q.front()]);
}
cout << ans << endl;
return 0;
}