Codeforces25E

题面

题目链接

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;
}
凡所不能将我击倒的,都将使我更加强大
原文地址:https://www.cnblogs.com/StarRoadTang/p/12935574.html