bzoj 3214: [Zjoi2013]丽洁体 贪心&动态规划

       显然两端的字符串要贪心找对吧,中间的那一段考虑类似于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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值