汕头市队赛 SRM 06 A 撕书

本文介绍了一个关于字符串匹配的问题:游行寺汀撕书过程中,如何判断一个子序列在特定时间内是否仍然存在。通过记录字符消失的时间,并采用二分搜索的方法来高效解决这一问题。

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后就不是了。

 

查找最大最小的 我一般都会先考虑二分 果不其然这道题就是了 nlogn 完全可做

我们可以记录每个点的消失(也就是被撕)的时间

二分时间求每次是否能匹配就可以了 2333

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=2e5+7;
char T[M],s[M];
int n,m,l,r,w[M];
int read(){
    int ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
int check(int k){
    int cnt=1;
    for(int i=1;i<=n;i++){
        if(w[i]<=k) continue;
        if(T[i]==s[cnt]) cnt++;
        if(cnt==m+1) return 1;
    }
    return 0;
}
int main()
{
    scanf("%s %s",T+1,s+1); 
    int k; 
    n=strlen(T+1); m=strlen(s+1);
    for(int i=1;i<=n;i++) k=read(),w[k]=i;
    l=1; r=n;
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
        else r=mid-1;
    }
    printf("%d\n",r);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/lyzuikeai/p/7191578.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值