Codeforces 762C Two Strings 二分判定+预处理

点击打开链接

题意:给出两个string a,b,长度<=1e5,求在b中删除最少的一段连续字符 使得b为a的子序列?  
删除字符要最小,若删除x个b为子序列,则删除y,y>=x个也肯定满足 二分答案
因为要删除的连续的一段,确定x之后 b只剩下某个前缀和某个后缀组成string


只要预处理出前缀i在a中匹配的子序列的最小下标结尾f[i],和后缀j在a中匹配的子序列的最大下标起点h[j]
若f[i]<h[i+x] 则b在a中形成子序列,O(n)判定即可

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+20;
string a,b,ans;
int len;
int f[N],h[N];
//f[i] b的前缀i在a中匹配的最小结尾
//h[i] b的后缀i在a中匹配的最大开头 
bool check(int x)
{
	for(int i=0;i<=len-x;i++)
	{
		//[0,i)+[i+x,len)
		string t= b.substr(0,i)+b.substr(i+x,len);
		if((i-1<0&&h[i+x]>=0)||f[i-1]<h[i+x])
		{
			ans=t;
			return true;
		}
	} 
	return false;
}
int main()
{
	while(cin>>a>>b)
	{
		len=b.length();
		int la=a.length();
		for(int i=0,j=0;i<len;i++,j++)//O(n+m) 
		{
			while(j<la&&a[j]!=b[i])
				j++;
			f[i]=j;
		}
		for(int i=len-1,j=la-1;i>=0;i--,j--)
		{
			while(j>=0&&a[j]!=b[i])
				j--;
			h[i]=j;
		}
		h[len]=a.length();///
		
		ans="-1";
		int l=0,r=len-1;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(check(mid))
			{
				r=mid-1;
			}
			else
			l=mid+1;
		}	
		if(ans!="-1")
			cout<<ans<<endl;
		else
			puts("-");
	} 
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值