题目链接:https://nanti.jisuanke.com/t/38232
题意:给出一个字符串s,接下来有q次查询,每次输入一个字符串t,求t是否是s的子串(可以不连续)。
倒着扫一次,预处理出每一位下一个字母出现的位置。字符串从下标1开始存储。
const int maxn=1e5+7;
char s[maxn];
char t[maxn];
int Next[maxn][27];
void init(int n){
memset(Next,0,sizeof(Next));
for(int i=n-1;i>=0;--i){
for(int j=0;j<26;++j)
Next[i][j]=Next[i+1][j];
Next[i][s[i+1]-'a']=i+1;
}
}
就相当于建立一颗二十六叉树,然后贪心的匹配出现的位置较前的字母。
从下标0(相当于空串)开始匹配,当匹配出现位置0的时候说明匹配失败(因为我们字符串是从1开始存的)。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
const int maxn=1e5+7;
char s[maxn];
char t[maxn];
int Next[maxn][27];
void init(int n){
for(int i=n-1;i>=0;--i){
for(int j=0;j<26;++j)
Next[i][j]=Next[i+1][j];
Next[i][s[i+1]-'a']=i+1;
}
}
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
init(n);
int q;
scanf("%d",&q);
while(q--){
scanf("%s",t);
int l=strlen(t);
int f=1;
int now=0;
for(int i=0;i<l;++i){
now=Next[now][t[i]-'a'];
if(now==0){
f=0;
break;
}
}
printf("%s\n",(f?"YES":"NO"));
}
return 0;
}