Luogu 无法提交 Codeforces 原题,解析已迁移至 codeforces/25E,本页仅保留入口。
OJ: luogu
题目 ID: CF25E
难度:普及+/提高
标签:KMP最短公共超串全排列
日期: 2026-07-16 19:57
题意
本题是 Codeforces 原题,Luogu 侧无法提交 CF 题目,完整解析(题意、思路、代码)已迁移至:
思路
枚举 right + '#' + left 求 pi,最后一位即重叠长度)。完整教学解析见 codeforces 页。
代码
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-08-02
* update_at: 2026-08-02
*/
/* CF25E Test */
/* 枚举 3! 种拼接顺序,每次把新串尽量重叠地接到当前串后面。 */
/* 重叠长度 = 对 right + '#' + left 求前缀函数,最后一位 pi 值。 */
#include <bits/stdc++.h>
using namespace std;
// 返回 left 的后缀与 right 的前缀的最大重叠长度
int overlap(const string &left, const string &right) {
// '#' 不会出现在小写字母中,保证 border 不会跨过分隔符:
// 整串 right#left 的 border 长度 k 满足 prefix(right,k) = suffix(left,k)
string t = right + "#" + left;
int m = (int)t.size();
vector<int> pi(m, 0);
for (int i = 1; i < m; i++) {
int j = pi[i - 1];
while (j > 0 && t[i] != t[j])
j = pi[j - 1];
if (t[i] == t[j])
j++;
pi[i] = j;
}
return pi[m - 1];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s[3];
cin >> s[0] >> s[1] >> s[2];
int p[3] = {0, 1, 2};
int ans = INT_MAX;
do {
string cur = s[p[0]];
for (int i = 1; i < 3; i++) {
const string &nxt = s[p[i]];
if (cur.find(nxt) != string::npos)
continue; // nxt 已被 cur 包含
if (nxt.find(cur) != string::npos) { // cur 被 nxt 包含,直接替换
cur = nxt;
continue;
}
cur += nxt.substr(overlap(cur, nxt)); // 只拼上不重叠的部分
}
ans = min(ans, (int)cur.size());
} while (next_permutation(p, p + 3));
cout << ans << '\n';
return 0;
}复杂度
排列数为常数,每次合并线性,总时间
总结
完整解析(含 Python 版本与思考过程)已迁移至 codeforces-25E Test。