Isfind

description

给定一长为\(n\)的字符串\(S\),给出\(m\)组询问.

每次询问给出一非空字符串\(\zeta\),判断此字符串是否是\(S\)的子序列.(未必要连续)

solution

水题.我们只需构造一个数组\(next[i][j]\)表示对于第\(i\)个位置下一个字符\(j\)的位置,然后查询即可.复杂度\(\Theta(n+\sum_{i=1}^{m}length(\zeta_{i}))\)

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define R register
#define next kdjadskfj
#define debug puts("mlg")
#define mod 10007 
#define Mod(x) ((x%mod+mod)%mod)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writeln(ll x);
inline void writesp(ll x);
ll n,m;
ll c[110000];
ll next[110000][27];
ll cnt,s[110000];
int main(){
	freopen("isfind.in","r",stdin);
	freopen("isfind.out","w",stdout);
	n=read();m=read();
	for(R ll i=1;i<=n;i++){
		char wn=getchar();
		while(wn<'a'||wn>'z') wn=getchar();
		c[i]=wn-'a'+1;
	}
	for(R ll i=n;i>=0;i--){
		for(R ll j=1;j<=26;j++){
			if(c[i+1]==j) next[i][j]=i+1;
			else next[i][j]=next[i+1][j];
		}
	}
	while(m--){
		cnt=0;
		char wn=getchar();
		while(wn<'a'||wn>'z') wn=getchar();
		while(wn>='a'&&wn<='z') s[++cnt]=wn-'a'+1,wn=getchar();
		ll now=0;
		bool flag=true;
		for(R ll i=1;i<=cnt;i++){
			if(!next[now][s[i]]){
				puts("N");flag=false;
				break;
			}
			now=next[now][s[i]];
		}
		if(flag) puts("Y");
	}
}
inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x);putchar(' ');}
inline void writeln(ll x){write(x);putchar('\n');}
posted @ 2020-08-03 17:17  月落乌啼算钱  阅读(223)  评论(0)    收藏  举报