显然两端的字符串要贪心找对吧,中间的那一段考虑类似于dp的方法。显然中间的需要找到最小的r-l,满足[l,r]中包含了给定的第二个串,然后我们中间的一位一位枚举,得到f[i]表示给定第二个串的前i位都满足的当前在中间段的最右处,然后令g[i]表示前i位满足且第i位最右的答案,然后用g[len S2]更新答案。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 500005
using namespace std;
int n,lena,lenb,lenc,s[N],a[N],b[N],c[N],fst[N],nxt[N],f[N],g[N];
struct hsh_node{
int tot,fst[2010527],pnt[N],sz[N],nxt[N];
int find(int x,bool flag){
int y=x%2010527,p;
for (p=fst[y]; p; p=nxt[p])
if (pnt[p]==x) return p;
if (!flag) return 0;
pnt[++tot]=x; nxt[tot]=fst[y]; fst[y]=tot; sz[tot]=1;
return tot;
}
}hsh;
void getin(int *a,int &n){
int x=0; char ch=getchar();
for (; ch!='\n'; ch=getchar())
if (ch>='a' && ch<='z') x=x*27+ch-'a'+1; else
if (x){ a[++n]=x; x=0; }
if (x) a[++n]=x;
}
int main(){
getin(s,n); int i,j,l,r,sum=0,ans=1000000000;
getin(a,lena); getin(b,lenb); getin(c,lenc);
for (i=1; i<=lenb; i++){
j=hsh.find(b[i],1);
nxt[i]=fst[j]; fst[j]=i;
}
for (l=i=1; i<=lena; l++)
if (s[l]==a[i]) i++; else sum++;
for (r=n,i=lenc; i; r--)
if (s[r]==c[i]) i--; else sum++;
memset(g,0x3f,sizeof(g));
for (i=l; i<=r; i++)
for (j=fst[hsh.find(s[i],0)]; j; j=nxt[j]){
if (j==1){
f[1]=i; g[1]=0;
} else if (f[j-1]){
f[j]=i; g[j]=g[j-1]+i-f[j-1]-1;
}
ans=min(ans,g[lenb]);
}
printf("%d\n",ans+sum);
return 0;
}
by lych
2016.5.17