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;
}