思路:
m次询问看字符串是不是给定字符串的子序列
暴力的做法就是直接两个循环去匹配 复杂度m * strlen(a) * Σ(strlen(b)) 这复杂度显然是不可接受的
那么考虑一下预处理
cnt[i][j] 表示当前位置为i下一个字符为j的位置 倒着遍历字符串即可
预处理一遍之后,每次循环跑的次数就只有strlen(b)
题中给定Σ(strlen(b)) 不大于1e6
而预处理的复杂度为 strlen(a) * 26
所以总共在3e7左右 这是允许的 然后既可以ac了
注意一下下标应该从1开始 或者你从0开始 但是表头位置是一个大于strlen(a)的位置也可以
就是说表头位置不能与字符串a的任一位置重叠(废话)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
char s[maxn],a[maxn];
int cnt[maxn][30];
int main(){
ios::sync_with_stdio(0);
memset(cnt,-1,sizeof cnt);///初始化都为-1
cin>>s+1;
int len=strlen(s+1);
for(int i=len-1;i>=0;i--){///倒序遍历给定的字符串
for(int j='a';j<='z';j++){
cnt[i][j-'a']=cnt[i+1][j-'a'];///把下一个位置的赋值给当前
}
cnt[i][s[i+1]-'a']=i+1;///下一个位置的字符覆盖掉
}
int m;cin>>m;
while(m--){
cin>>a+1;
int len=strlen(a+1),flag=0,now=0;
for(int i=1;i<=len;i++){
if(cnt[now][a[i]-'a']!=-1){///说明存在下一个字符的位置
now=cnt[now][a[i]-'a'];///位置移动的下一个字符的位置
}
else {///不存在下一个字符
flag=1;
break;
}
}
if(flag) cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
return 0;
}
京公网安备 11010502036488号