题解:CF1455F String and Operations
首先我们发现一个点最多被交换两次,所以首先我们可以记忆化搜索,设 map 记忆化,加上很多剪枝后可以发现只有
发现复杂度瓶颈在于字符串的存储和比较,所以我们不存字符串了,我们存转移点,并用倍增维护哈希值,从而实现单次
这样大约跑 map 记忆化,所以不容易过去。
注意到每一种状态都可以变进制哈希成一个小于 map 这个
代码:
#include <bits/stdc++.h>
#define ls(x) ((x) << 1)
#define rs(x) ((x) << 1 | 1)
using namespace std;
const int N = 1e6 + 5;
int t, idx;
int n, k;
char s[N];
unsigned long long c[N];
bool f[N];
struct node {
int i, q1, q2, q3, at;
};
node d[N];
int id[40 * N];
int st[12][20005];
unsigned long long h[12][20005];
inline unsigned long long hs (const int i, const int q1, const int q2, const int q3, const int at) {
unsigned long long h = i;
h = h * 26 + q1;
h = h * 26 + q2;
h = h * 26 + q3;
h = h * 4 + at;
return h;
}
inline unsigned long long hs (const node &a) {
unsigned long long h = a.i;
h = h * 26 + a.q1;
h = h * 26 + a.q2;
h = h * 26 + a.q3;
h = h * 4 + a.at;
return h;
}
int cnt;
inline void Dfs (const int i, const int q1, const int q2, const int q3, const int at) {
unsigned long long now = hs(i, q1, q2, q3, at);
if (i > n) {
if (id[now]) return;
d[ ++ idx] = {i, q1, q2, q3, at};
id[now] = idx;
d[ ++ idx] = {i + 1, q2, q3, 0, at};
id[hs({i + 1, q2, q3, 0, at})] = idx;
return;
}
if (id[now]) return;
d[ ++ idx] = {i, q1, q2, q3, at};
id[now] = idx;
if (at == 2) {
if (q1 != q2) {
if (q1 < q2) {
if (q3 < min((q2 + 1) % k, (q2 - 1 + k) % k)) {
Dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
} else if (q3 > min((q2 + 1) % k, (q2 - 1 + k) % k)) {
Dfs (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
} else {
Dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
Dfs (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
}
} else {
Dfs (i + 1, q1, q3, s[i + 1] - 'a', 3);
}
} else {
Dfs (i + 1, q1, q3, s[i + 1] - 'a', 3);
Dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
Dfs (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
}
} else {
if (q3 < q2) {
Dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
} else if (q3 > q2) {
Dfs (i + 1, q2, min((q3 + 1) % k, (q3 - 1 + k) % k), s[i + 1] - 'a', 3);
} else {
Dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
Dfs (i + 1, q2, min((q3 + 1) % k, (q3 - 1 + k) % k), s[i + 1] - 'a', 3);
}
if (i != n) {
Dfs (i + 1, q2, s[i + 1] - 'a', q3, 2);
}
}
return;
}
inline void DFS (const int i, const int q1, const int q2, const int q3, const int at) {
unsigned long long now = hs(i, q1, q2, q3, at);
if (i > n) {
if (!id[now]) return;
f[id[now]] = false;
id[now] = 0;
f[id[hs({i + 1, q2, q3, 0, at})]] = false;
id[hs({i + 1, q2, q3, 0, at})] = 0;
return;
}
if (!id[now]) return;
f[id[now]] = false;
id[now] = 0;
if (at == 2) {
if (q1 != q2) {
if (q1 < q2) {
if (q3 < min((q2 + 1) % k, (q2 - 1 + k) % k)) {
DFS (i + 1, q3, q2, s[i + 1] - 'a', 3);
} else if (q3 > min((q2 + 1) % k, (q2 - 1 + k) % k)) {
DFS (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
} else {
DFS (i + 1, q3, q2, s[i + 1] - 'a', 3);
DFS (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
}
} else {
DFS (i + 1, q1, q3, s[i + 1] - 'a', 3);
}
} else {
DFS (i + 1, q1, q3, s[i + 1] - 'a', 3);
DFS (i + 1, q3, q2, s[i + 1] - 'a', 3);
DFS (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
}
} else {
if (q3 < q2) {
DFS (i + 1, q3, q2, s[i + 1] - 'a', 3);
} else if (q3 > q2) {
DFS (i + 1, q2, min((q3 + 1) % k, (q3 - 1 + k) % k), s[i + 1] - 'a', 3);
} else {
DFS (i + 1, q3, q2, s[i + 1] - 'a', 3);
DFS (i + 1, q2, min((q3 + 1) % k, (q3 - 1 + k) % k), s[i + 1] - 'a', 3);
}
if (i != n) {
DFS (i + 1, q2, s[i + 1] - 'a', q3, 2);
}
}
return;
}
inline void dfs (const int i, const int q1, const int q2, const int q3, const int at) {
int now = id[hs(i, q1, q2, q3, at)];
if (i > n) {
h[0][now] = q1 + 'a';
int t = id[hs({i + 1, q2, q3, 0, at})];
st[0][now] = t;
h[0][t] = q2 + 'a';
for (int j = 1; j <= 10; ++ j ) {
st[j][now] = t;
h[j][now] = h[j - 1][now] * c[1 << (j - 1)] + h[j - 1][st[j - 1][now]];
}
return;
}
if (f[now]) return;
f[now] = true;
if (at == 2) {
if (q1 != q2) {
if (q1 < q2) {
if (q3 < min((q2 + 1) % k, (q2 - 1 + k) % k)) {
st[0][now] = id[hs({i + 1, q3, q2, s[i + 1] - 'a', 3})];
h[0][now] = q1 + 'a';
dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
} else if (q3 > min((q2 + 1) % k, (q2 - 1 + k) % k)) {
st[0][now] = id[hs({i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3})];
h[0][now] = q1 + 'a';
dfs (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
} else {
const int U = id[hs({i + 1, q3, q2, s[i + 1] - 'a', 3})], V = id[hs({i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3})];
int u = U, v = V;
dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
dfs (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
int cnt = 0;
for (int i = 10; i >= 0; -- i ) {
if (h[i][u] == h[i][v]) {
u = st[i][u], v = st[i][v];
cnt += 1 << i;
}
}
if (cnt >= 1e3) {
st[0][now] = U;
h[0][now] = q1 + 'a';
} else if (h[0][u] < h[0][v]) {
st[0][now] = U;
h[0][now] = q1 + 'a';
} else {
st[0][now] = V;
h[0][now] = q1 + 'a';
}
}
} else {
st[0][now] = id[hs({i + 1, q1, q3, s[i + 1] - 'a', 3})];
h[0][now] = q2 + 'a';
dfs (i + 1, q1, q3, s[i + 1] - 'a', 3);
}
} else {
h[0][now] = q2 + 'a';
dfs (i + 1, q1, q3, s[i + 1] - 'a', 3);
dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
dfs (i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3);
const int U = id[hs({i + 1, q1, q3, s[i + 1] - 'a', 3})], V = id[hs({i + 1, q3, q2, s[i + 1] - 'a', 3})];
int u = U, v = V;
int cnt = 0;
for (int i = 10; i >= 0; -- i ) {
if (h[i][u] == h[i][v]) {
u = st[i][u], v = st[i][v];
cnt += 1 << i;
}
}
if (cnt >= 1e3) u = U;
else if (h[0][u] < h[0][v]) {
u = V;
} else {
u = V;
}
int tmp = u;
const int T = id[hs({i + 1, min((q2 + 1) % k, (q2 - 1 + k) % k), q3, s[i + 1] - 'a', 3})];
v = T;
cnt = 0;
for (int i = 10; i >= 0; -- i ) {
if (h[i][u] == h[i][v]) {
u = st[i][u], v = st[i][v];
cnt += 1 << i;
}
}
if (cnt >= 1e3) u = tmp;
else if (h[0][u] < h[0][v]) u = tmp;
else u = T;
st[0][now] = u;
}
} else {
h[0][now] = q1 + 'a';
int u, v;
if (q3 < q2) {
dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
u = id[hs({i + 1, q3, q2, s[i + 1] - 'a', 3})];
} else if (q3 > q2) {
dfs (i + 1, q2, min((q3 + 1) % k, (q3 - 1 + k) % k), s[i + 1] - 'a', 3);
u = id[hs({i + 1, q2, min((q3 + 1) % k, (q3 - 1 + k) % k), s[i + 1] - 'a', 3})];
} else {
dfs (i + 1, q3, q2, s[i + 1] - 'a', 3);
dfs (i + 1, q2, min((q3 + 1) % k, (q3 - 1 + k) % k), s[i + 1] - 'a', 3);
const int U = id[hs({i + 1, q3, q2, s[i + 1] - 'a', 3})], V = id[hs({i + 1, q2, min((q3 + 1) % k, (q3 - 1 + k) % k), s[i + 1] - 'a', 3})];
u = U, v = V;
int cnt = 0;
for (int i = 10; i >= 0; -- i ) {
if (h[i][u] == h[i][v]) {
u = st[i][u], v = st[i][v];
cnt += 1 << i;
}
}
if (cnt >= 1e3) u = U;
else if (h[0][u] < h[0][v]) u = U;
else u = V;
}
if (i != n) {
const int tmp = u;
const int T = id[hs({i + 1, q2, s[i + 1] - 'a', q3, 2})];
v = T;
dfs (i + 1, q2, s[i + 1] - 'a', q3, 2);
int cnt = 0;
for (int i = 10; i >= 0; -- i ) {
if (h[i][u] == h[i][v]) {
u = st[i][u], v = st[i][v];
cnt += 1 << i;
}
}
if (cnt >= 1e3) u = tmp;
else if (h[0][u] < h[0][v]) u = tmp;
else u = T;
}
st[0][now] = u;
}
for (int j = 1; j <= 10; ++ j ) {
st[j][now] = st[j - 1][st[j - 1][now]];
h[j][now] = h[j - 1][now] * c[1 << (j - 1)] + h[j - 1][st[j - 1][now]];
}
return;
}
signed main() {
// freopen("g.in","r",stdin);
// freopen("g.out","w",stdout);
c[0] = 1;
for (int i = 1; i <= 1e6; ++ i ) c[i] = c[i - 1] * 33331;
scanf("%d", &t);
while (t -- ) {
for (int i = 1; i <= idx; ++ i ) {
for (int j = 0; j <= 10; ++ j ) {
st[j][i] = h[j][i] = 0;
}
}
idx = 0;
scanf("%d%d%s", &n, &k, s + 1);
s[n + 1] = 'z';
Dfs (1, 0, 0, s[1] - 'a', 3);
dfs (1, 0, 0, s[1] - 'a', 3);
int u = id[hs({1, 0, 0, s[1] - 'a', 3})];
for (int i = 1; i <= n + 2; ++ i ) {
if (i > 2) printf("%c", (char)h[0][u]);
u = st[0][u];
}
puts("");
DFS (1, 0, 0, s[1] - 'a', 3);
}
return 0;
}