题意
给定字符串 ,有 个询问,每个询问给出一个字符串 , 问 是否是 的子序列。
分析
先记录每个字母在 中出现的位置。
对于字符串 的每个 ,我们肯定尽可能在 中往前取。
假设上一次取的是 。
那么这一次就要在所有 出现的位置中找到第一个比 大的。这个可以二分解决。
代码如下
#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; }