题意

给定字符串 ,有 个询问,每个询问给出一个字符串 , 问 是否是 的子序列。

分析

先记录每个字母在 中出现的位置。
对于字符串 的每个 ,我们肯定尽可能在 中往前取。
假设上一次取的是
那么这一次就要在所有 出现的位置中找到第一个比 大的。这个可以二分解决。

代码如下

#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;
}