原题
给你三个字符串,找一个字符串(它的子串含有以上三个字符串),输出此字符串的长度。
先暴力判断是否有包含,消减需要匹配的串的数量。因为只有三个字符串,所以暴力枚举三个串的位置关系,对三个串跑好哈希,然后判断后缀与前缀重合长度即可。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define mo 99994711
typedef long long ll;
using namespace std;
int is1=1,is2=1,all=3,base=1314,ord[4],ans,l[4];
long long num[4][100010],bs[100010];
bool vis[4];
char s[4][100010];
ll gethash(int x,int st,int l)
{
ll ans=0;
ans=bs[100005-st]*(num[x][st+l-1]-(st==0? 0 : num[x][st-1]))%mo;
return (ans%mo+mo)%mo;
}
bool in(int x,int y)
{
ll u,v;
for (int i=0;i<l[y]-l[x];i++)
{
u=gethash(y,i,l[x]);
v=num[x][l[x]-1]*bs[100005]%mo;
if (u==v) return 1;
}
return 0;
}
int mini(int x,int y)
{
ll u,v;
int ans=0;
for (int i=1;i<=min(l[x],l[y]);i++)
{
u=gethash(x,l[x]-i,i);
v=gethash(y,0,i);
if (u==v) ans=i;
}
return ans;
}
void hsh(int x)
{
for (int i=0;i<l[x];i++)
if (i) num[x][i]=(num[x][i-1]+(ll)(s[x][i]-'a'+1)*bs[i])%mo;
else num[x][i]=s[x][i]-'a'+1;
}
void dfs(int x)
{
if (x>3)
{
ans=min(ans,l[1]+l[2]+l[3]-mini(ord[1],ord[2])-mini(ord[2],ord[3]));
return ;
}
for (int i=1;i<=3;i++)
if (!vis[i])
{
vis[i]=1;
ord[x]=i;
dfs(x+1);
vis[i]=0;
}
}
void st()
{
if (l[1]>l[2]) swap(l[1],l[2]),swap(s[1],s[2]);
if (l[2]>l[3]) swap(l[2],l[3]),swap(s[2],s[3]);
if (l[1]>l[2]) swap(l[1],l[2]),swap(s[1],s[2]);
}
int main()
{
ans=0x7fffffff;
bs[0]=1;
for (int i=1;i<=100005;i++) bs[i]=bs[i-1]*base%mo;
scanf("%s%s%s",s[1],s[2],s[3]);
l[1]=strlen(s[1]);
l[2]=strlen(s[2]);
l[3]=strlen(s[3]);
st();
hsh(1);
hsh(2);
hsh(3);
if (in(1,2)) is1=0,all--;
if (in(2,3)) is2=0,all--;
if (is1 && in(1,3)) is1=0,all--;
if (all==1)
{
printf("%d
",l[3]);
return 0;
}
if (all==2)
{
if (!is2 && is1) swap(s[1],s[2]),swap(l[1],l[2]);
hsh(2);
hsh(3);
printf("%d
",l[2]+l[3]-max(mini(2,3),mini(3,2)));
}
else
{
dfs(1);
printf("%d
",ans);
}
return 0;
}