codeforces 778A String Game&&汕头市队赛SRM06A

A 撕书 SRM 06

背景&&描述

        游行寺汀正在杀书。
        书总共有n页,每页都可以看作是一个小写英文字母,所以我们可以把书看成长度为n的字符串s。
        琉璃静静地在旁边看着。根据他对汀的了解,汀+1s只会撕一页。令a_{i}表示第i秒撕的是哪一页,显然a是1..n的一个排列。
        琉璃突然对s的一个非空子序列t产生了兴趣。他想知道,最多在汀撕多少页之后,t仍然是剩下的书的某个子序列。

 

输入格式

        第一行一个字符串,表示s

        第二行一个字符串,表示t

        第三行n个整数(n为s的长度),表示a

输出格式

一个整数,表示最多在汀撕多少页之后,t仍然是剩下的书的某个子序列。

样例输入
sbkitssakitsak
kisaki
1 14 13 2 6 12 9 10 5 3 8 4 7 11
样例输出
6
数据范围与约定
  • 对于100%的数据:1\leq n\leq 2*10^5
样例解释

6s后,剩下的书为kitsakit,此时kisaki还是书的子序列。第7s撕掉第二个k后就不是了。


我上的是我们市队赛的题面

跟codeforces的唯一区别是那个没有保证给的一定是书的子序列

把二分边界改一下就好了

这题得orz一波yy大爷

我自己根本没想出要二分

以后这种求最大最小的得往二分上面想啊

yy大爷的处理也很巧妙啊

想到要记录每个位置是哪一次删的

这样直接扫一遍就可以了

我本来还想着要去删的委屈

然后二分最后跨度为1的时候如果写在二分里面挺难处理的(起码我感觉是)

所以我直接break出来判一下就好了

#include<cstdio>
#include<cstring>
const int N=200007;
char a[N],b[N];
int t[N];
int n,m;
bool check(int x)
{
	for(int i=1,j=1;i<=n;i++)
	{
		if(t[i]<=x)	continue;
		if(a[i]==b[j])	j++;
		if(j==m+1)	return 1;
	}
	return 0;
}
int main()
{
	scanf("%s %s",a+1,b+1);
	n=strlen(a+1),m=strlen(b+1);
	int k;
	for(int i=1;i<=n;i++)	scanf("%d",&k),t[k]=i;
	int ll=0,rr=n;
	while(rr-ll>1)
	{
		int mid=(ll+rr)>>1;
//		printf("%d %d %d\n",ll,rr,mid);
		if(check(mid))	ll=mid;
		else rr=mid-1;
	}
	if(check(rr))	printf("%d\n",rr);
	else printf("%d\n",ll);
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值