P6095 [JSOI2015]串分割
P6095 [JSOI2015]串分割
因为字符不含
答案满足可二分性。我们二分答案在后缀数组中的排名。破环成链,枚举
若可匹配
进一步地,比较两个长度为
但其实没有关系,因为若
时间复杂度
#include <bits/stdc++.h>
using namespace std;
bool Mbe;
constexpr int N = 4e5 + 5;
int n, k, len;
char s[N];
int rk[N], ork[N], sa[N], buc[N], id[N];
bool cmp(int a, int b, int w) {return ork[a] == ork[b] && ork[a + w] == ork[b + w];}
void build() {
int m = 1 << 7, p = 0;
for(int i = 1; i <= n; i++) buc[rk[i] = s[i]]++;
for(int i = 1; i <= m; i++) buc[i] += buc[i - 1];
for(int i = n; i; i--) sa[buc[rk[i]]--] = i;
for(int w = 1; ; w <<= 1, m = p, p = 0) {
for(int i = n - w + 1; i <= n; i++) id[++p] = i;
for(int i = 1; i <= n; i++) if(sa[i] > w) id[++p] = sa[i] - w;
memset(buc, 0, sizeof(buc));
memcpy(ork, rk, sizeof(rk));
p = 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; i--) sa[buc[rk[id[i]]]--] = id[i];
for(int i = 1; i <= n; i++) rk[sa[i]] = cmp(sa[i - 1], sa[i], w) ? p : ++p;
if(p == n) break;
}
}
bool Med;
int main() {
fprintf(stderr, "%.4lf\n", (&Mbe - &Med) / 1048576.0);
#ifdef ALEX_WEI
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
#endif
cin >> n >> k >> s + 1, len = (n - 1) / k + 1;
for(int i = 1; i <= n; i++) s[i + n] = s[i];
n <<= 1, build();
int l = 1, r = n, m = n >> 1;
while(l < r) {
int mid = l + r >> 1, ok = 0;
for(int i = 1; i <= len; i++) {
int cur = 0;
for(int j = 1; j <= k; j++) {
int p = (i + cur - 1) % m + 1;
if(rk[p] <= mid) cur += len;
else cur += len - 1;
}
ok |= cur >= m;
}
if(ok) r = mid;
else l = mid + 1;
}
for(int i = 0; i < len; i++) cout << s[sa[l] + i];
return cerr << "Time: " << clock() << "\n", 0;
}
/*
2022/7/2
start coding at 18:24
finish debugging at 18:36
*/