SP7155 CF25E - Test (kmp&暴力)
题意
求包含三个字符串为子串的最短串长度。
思路
预处理两两字符串kmp匹配的最大长度。
然后暴力跑,分四种情况计算答案。
代码
// Problem: E. Test
// Contest: Codeforces - Codeforces Beta Round #25 (Div. 2 Only)
// URL: https://codeforces.ml/contest/25/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// Date: 2021-03-03 21:57:35
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
// kmp
int p[N];
void Gnt(char *a){
int n=strlen(a+1),j=0;
p[0]=p[1]=0;
for(int i=2;i<=n;i++){
while(j&&a[i]!=a[j+1]) j=p[j];
if(a[i]==a[j+1]) j++;
p[i]=j;
}
}
int kmp(char *a,char *b){
Gnt(b);
int n=strlen(a+1),m=strlen(b+1);
int j=0;
for(int i=1;i<=n;i++){
while(j&&a[i]!=b[j+1]) j=p[j];
if(a[i]==b[j+1]) j++;
if(j==m){
return -1;
}
}
return j;
}
int f[3][3],len[3];
char a[3][N];
int fun(int a,int b,int c){
//四种情况:
//b,c都不是a子串
//b,c都是a子串
//b,c其中一个是a子串
if(f[a][b]>=0&&f[b][c]>=0) return f[a][b]+f[b][c];
else if(f[a][b]<0&&f[a][c]<0) return len[b]+len[c];
else if(f[a][b]<0) return len[b]+f[a][c];
else return f[a][b]+len[c];
}
int main(){
while(scanf("%s%s%s",a[0]+1,a[1]+1,a[2]+1)==3){
int tot=0;
for(int i=0;i<3;i++) len[i]=strlen(a[i]+1),tot+=len[i];
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(i!=j) f[i][j]=kmp(a[i],a[j]);
int ans=0;
int b[3]={0,1,2};
do{
ans=max(ans,fun(b[0],b[1],b[2]));
}while(next_permutation(b,b+3));
printf("%d\n",tot-ans);
}
return 0;
}