您的位置:首页 > 其它

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

2017-04-15 11:04 435 查看
点击打开链接

题意:给出两个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
,h
;
//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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: