我的代码和题解主体思路一样但是细节不同,现在一直是只有最后一组 WA
,小范围数据拍了几千组无果,最后一组数据又下不下来,有哪位好心人愿意提供一下数据或坑点或帮我 debug 一下吗?谢谢!
#include <bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define rep(i, s, e) for (re int i = s; i <= e; ++i)
#define drep(i, s, e) for (re int i = s; i >= e; --i)
#define file(a) freopen(#a".in", "r", stdin), freopen(#a".out", "w", stdout)
const int N = 4000 + 10;
const int K = 20000 + 10;
il int read() {
int x = 0; bool f = true; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = false; c = getchar();}
while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? x : -x;
}
int z[K];
il void Z(char *s, int n) {
rep(i, 1, n) z[i] = 0;
z[1] = n;
for (int i = 2, l = 0, r = 0; i <= n; ++i) {
if (i <= r) z[i] = min(z[i - l + 1], r - i + 1);
while (i + z[i] <= n && s[i + z[i]] == s[z[i] + 1]) ++z[i];
if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
}
}
int p[N];
il void exkmp(char *s, int n, char *t, int m) {
Z(t, m);
rep(i, 1, n) p[i] = 0;
for (int i = 1, l = 0, r = 0; i <= n; ++i) {
if (i <= r) p[i] = min(z[i - l + 1], r - i + 1);
while (i + p[i] <= n && p[i] < m && s[i + p[i]] == t[p[i] + 1]) ++p[i];
if (i + p[i] - 1 > r) l = i, r = i + p[i] - 1;
}
}
int n, k, len[N], mlen[N];
char s[N][K], mth[N][K], tmp[K];
bitset <K> P[N], S[N], can[N], ret[N];
int main() {
file(data);
n = read(), k = read();
rep(i, 1, n) scanf("%s", s[i] + 1), len[i] = strlen(s[i] + 1);
P[0][0] = 1, S[n + 1][0] = 1;
rep(i, 1, n) P[i] = P[i - 1] | (P[i - 1] << len[i]);
drep(i, n, 1) S[i] = S[i + 1] | (S[i + 1] << len[i]);
rep(i, 1, n) rep(j, 0, k) can[i][j] = P[i][j] & S[i + 1][k - j];
ret[0][0] = 1;
rep(i, 1, n) {
mlen[i] = mlen[i - 1];
rep(j, 1, mlen[i - 1]) tmp[j] = mth[i][j] = mth[i - 1][j];
rep(j, 1, len[i]) tmp[mlen[i - 1] + j] = s[i][j];
exkmp(tmp, mlen[i - 1] + len[i], s[i], len[i]);
int pos = -1;
rep(j, 0, mlen[i - 1]) {
if (!ret[i - 1][j] || !can[i][j + len[i]]) continue;
if (p[j + 1] < len[i] && (can[i][mlen[i - 1] + len[i]] || j + p[j + 1] < mlen[i - 1]) && tmp[j + 1 + p[j + 1]] < s[i][p[j + 1] + 1]) continue;
if (p[j + 1] == len[i] && j + len[i] <= mlen[i - 1]) continue;
if (p[j + 1] == len[i]) {
if (pos == -1 || p[pos + 1] == len[i]) pos = j;
else if (tmp[pos + 1 + p[pos + 1]] < s[i][p[pos + 1] + 1]) pos = j;
continue;
}
if (pos == -1) { pos = j; continue; }
if (pos + p[pos + 1] < j + p[j + 1]) {
if (tmp[pos + 1 + p[pos + 1]] < s[i][p[pos + 1] + 1]) pos = j;
continue;
}
else if (pos + p[pos + 1] == j + p[j + 1]) {
int d = j - pos, l = z[d + 1];
if (l < len[i] - d) {
if (s[i][d + 1 + l] > s[i][l + 1]) pos = j;
continue;
}
else {
bool flag = true;
rep(rnm, len[i] - d + 1, len[i]) {
if (!can[i][mlen[i - 1] + len[i]] && j + rnm - 1 > mlen[i - 1]) break;
if (s[i][rnm] < tmp[j + rnm - 1]) break;
else if (s[i][rnm] > tmp[j + rnm - 1]) { flag = false; break; }
}
if (flag) pos = j;
continue;
}
}
else {
if (tmp[j + 1 + p[j + 1]] > s[i][p[j + 1] + 1]) pos = j;
continue;
}
}
if (pos == -1) {
mlen[i] = mlen[i - 1], ret[i] = ret[i - 1];
rep(j, 1, mlen[i]) mth[i][j] = mth[i - 1][j];
rep(j, 0, mlen[i] - len[i]) if (ret[i - 1][j] && p[j + 1] == len[i]) ret[i][j + len[i]] = true;
}
else {
mlen[i] = pos + len[i], ret[i][mlen[i]] = true;
rep(j, 1, pos) mth[i][j] = mth[i - 1][j];
rep(j, 1, len[i]) mth[i][pos + j] = s[i][j];
rep(j, 0, pos) if (ret[i - 1][j]) ret[i][j] = true;
rep(j, 1, len[i]) {
if (pos + j > mlen[i - 1] || mth[i - 1][pos + j] != s[i][j]) break;
if (ret[i - 1][pos + j]) ret[i][pos + j] = true;
}
rep(j, 0, pos) {
if (!ret[i - 1][j]) continue;
if (j + len[i] <= pos) {
if (p[j + 1] == len[i]) ret[i][j + len[i]] = true;
}
else {
int d = pos - j;
if (p[j + 1] >= d && z[d + 1] == len[i] - d) ret[i][j + len[i]] = true;
}
}
}
}
rep(i, 1, k) printf("%c", mth[n][i]);
puts("");
return 0;
}