题解:CF2225F String Cutting
奶奶题目不光卡我单模哈希,双模哈希底数选
诈骗题。
首先分成
枚举一个
时间复杂度
:::success[CODE]
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e+6 + 6;
int T, n, m, k;
char s[maxn];
struct Hash {
int base, mod;
int f[maxn], g[maxn];
inline void init() {
g[0] = 1;
for (int i = 1; i <= n; i++) {
f[i] = (f[i - 1] * base % mod + s[i]) % mod;
g[i] = g[i - 1] * base % mod;
}
}
inline int ret(int l, int r) {
return (f[r] - f[l - 1] * g[r - l + 1] % mod + mod) % mod;
}
}h1, h2;
inline bool chk(int l1, int r1, int l2, int r2) {
int l = 1, r = min(r1 - l1 + 1, r2 - l2 + 1), res = 0;
while (l <= r) {
int mid = (l + r) / 2;
if (h1.ret(l1, l1 + mid - 1) == h1.ret(l2, l2 + mid - 1) && h2.ret(l1, l1 + mid - 1) == h2.ret(l2, l2 + mid - 1)) {
res = mid;
l = mid + 1;
} else r = mid - 1;
}
if (res == min(r1 - l1 + 1, r2 - l2 + 1)) return r1 - l1 + 1 < r2 - l2 + 1;
return s[l1 + res] < s[l2 + res];
}
inline void GOGOGO() {
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) {
cin >> s[i];
}
h1.init(), h2.init();
int l = 0, r = 0;
for (int i = 1; i + m - 1 <= n; i++) {
if (i != 1 && i <= m) continue;
int cnt = (i - 1) / m;
cnt = k - cnt - 1;
if (cnt < 0) {
if (k == 1) break;
cnt = 0;
}
cnt *= m;
int j = n - cnt;
if (j - i + 1 < m) continue;
if (!l || chk(l, r, i, j)) {
l = i;
r = j;
}
}
if (!l) cout << "NO" << '\n';
else {
cout << "YES" << '\n';
for (int i = l; i <= r; i++) cout << s[i];
cout << '\n';
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> T;
h1.base = 97, h1.mod = 998244353;
h2.base = 101, h2.mod = 1e+9 + 7;
while (T--) GOGOGO();
return 0;
}
:::