这题搞的我真的是快崩溃了,题意说的有点不清楚,有可能是我太蠢,没注意到是子串就不用再加一串的情况,2个小时的kmp,纪念一下8。
题意:
给你三个字符串a,b,c, 现在让你构造一个字符串,条件是这个字符串中能找到a,b,c这三个子串(这个子串是要连续的),现在问你构造的最短长度是多少。
思路:
一开始想的是假如a后面是b,那么就要求一下a的后缀和b的前缀的公共部分,用same[i][j]来表示这个公共部分的长度,然后我就搞了一下(b+a)这个串的next数组,公共部分就是next[len(a+b)](真的nt),其实可以用kmp求,最后如果匹配到了,就直接return那个模式串的长度,没匹配到最后就return最后匹配到的模式串的下标,也就是模式串的前缀和主串的后缀匹配的长度。
接下来就三个for枚举a,b,c依次连起来所需的长度,有个情况要注意一下,b是a的子串,并且c也是a的子串,那就要单独拿出来考虑,所需长度就是len[a],(罚时+1h)。剩下的情况
1.b是a的子串,那么因为c肯定不是a的子串咯,而且现在c要连在a后面,所以+len[a]+len[c]-same[a][c]。
2.c是a的子串,那么因为b不是a的子串,所以+len[a]+len[b]-same[a][b]。
3.没有子串关系,所以+len[a]+len[b]+len[c]-same[a][b]-same[b][c]。
#include <bits/stdc++.h>
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, a, b) for (int i = (int)(a); i >= (int)b; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define ms(x, y) memset(x, y, sizeof(x))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef pair<i64, i64> pi64;
typedef double ld;
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }
const int maxn = 2*(int)1e5+1000;
char s[3][maxn], x[maxn];
int len[3], nxt[maxn], same[3][3];
void kmp_pre(char x[], int m, int nxt[]) {
int i, j;
j = nxt[0] = -1;
i = 0;
while (i <= m) {
while (-1 != j && x[i] != x[j]) j = nxt[j];
nxt[++i] = ++j;
}
}
int kmp_count(char x[], int m, char y[], int n) {
int i, j;
int ans = 0;
kmp_pre(x, m, nxt);
i = j = 0;
while (i < n) {
while (-1 != j && y[i] != x[j]) j = nxt[j];
++i;
++j;
if (j >= m) {
return m;
++ans;
j = nxt[j];
}
}
return j;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFINE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
while (cin >> s[0] && cin >> s[1] && cin >> s[2]) {
for (int i = 0; i < 3; ++i) len[i] = strlen(s[i]);
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (i == j) continue;
int temp = kmp_count(s[j], len[j], s[i], len[i]);
same[i][j] = temp;
}
}
int ans = INT_MAX;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (j == i) continue;
for (int k = 0; k < 3; ++k) {
if (k == j || k == i) continue;
if (same[i][j] == len[j] && same[i][k] == len[k]) ans = min(ans, len[i]);
else if (same[i][j] == len[j]) ans = min(ans, len[i]+len[k]-same[i][k]);
else if (same[j][k] == len[k]) ans = min(ans, len[i]+len[j]-same[i][j]);
else {
ans = min(ans, len[i]+len[j]+len[k]-same[i][j]-same[j][k]);
}
}
}
}
cout << ans << '\n';
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}