题意
给定字符串 ,有
个询问,每个询问给出一个字符串
, 问
是否是
的子序列。
分析
先记录每个字母在 中出现的位置。
对于字符串 的每个
,我们肯定尽可能在
中往前取。
假设上一次取的是 。
那么这一次就要在所有 出现的位置中找到第一个比
大的。这个可以二分解决。
代码如下
#include <bits/stdc++.h>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#define N 1000005
using namespace __gnu_pbds;
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
struct custom_hash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
LL z = 1;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
int ksm(int a, int b, int p){
int s = 1;
while(b){
if(b & 1) s = z * s * a % p;
a = z * a * a % p;
b >>= 1;
}
return s;
}
vector<int> vec[155];
char s[N], t[N];
int main(){
int i, j, n, m, l, p, flag;
scanf("%s", s + 1);
n = strlen(s + 1);
for(i = 1; i <= n; i++) vec[s[i]].push_back(i);
m = read();
while(m--){
scanf("%s", t + 1);
l = strlen(t + 1);
flag = p = 0;
for(i = 1; i <= l; i++){
j = vec[t[i]].size();
if(!j || vec[t[i]][j - 1] <= p){
flag = 1;
break;
}
j = upper_bound(vec[t[i]].begin(), vec[t[i]].end(), p) - vec[t[i]].begin();
p = vec[t[i]][j];
}
if(flag) printf("No\n");
else printf("Yes\n");
}
return 0;
}
京公网安备 11010502036488号