题面
题目链接
https://codeforces.com/contest/25/problem/E
题目大意
给定3个字符串s1 , s2 , s3 , 试求一个字符串 S
使 s1 , s2 , s3 都是这个字符串的子串,问这个字符串最短是多少
解题思路
显然最坏的情况是 s1 s2 s3 直接拼接起来 , 即 S = s1s2s3 / s1s3s3 / s2s1s3 / s2s3s1 / s3s1s2 / s3s2s1
以 S = s1s2s3 为例,当 s2 是 s1 的子串时,我们就不需要再对 s1 拼接 s2 了,因为此时的 s1 已经包含了 s2 了(废话) ,s3 同理
而当 s1 不是 s2 的子串时,若 s1 的后缀 和 s2 的前缀相匹配(相等),我们就可以只取 s2 未匹配的后缀拼接到 s1 上,然后再拿拼接后的串和 s3 匹配,再把 s3 剩下未匹配的后缀拼接上即可得到该例的最优解
于是这题就成了一道很裸的 kmp 题了
AC_Code
#include<bits/stdc++.h> using namespace std; const int N = 3e5 + 10; string s[N] ; int nex[N]; void get_nex(string s , int *nex) { int i = 0 , j = -1 , len = s.size(); nex[i] = j; while(i < len) { while(j != -1 && s[i] != s[j]) j = nex[j]; nex[++ i] = ++ j ; } } int KMP(string s , string t) { get_nex(t , nex) ; int i = 0 , j = 0 , lens = s.size() , lent = t.size(); while(i < lens) { while(j != -1 && s[i] != t[j]) j = nex[j]; i ++ , j ++ ; if(j == lent) return lent; } return j; } int solve(string a , string b , string c) { int pos = KMP(a , b); a += b.substr(pos , b.size() - pos); pos = KMP(a , c); return a.size() + c.size() - pos; } signed main() { ios::sync_with_stdio(false); cin >> s[1] >> s[2] >> s[3]; sort(s + 1 , s + 1 + 3); int ans = s[1].size() + s[2].size() + s[3].size(); do{ ans = min(ans , solve(s[1] , s[2] , s[3])); }while(next_permutation(s + 1 , s + 1 + 3)); cout << ans << ' ' ; return 0; }