问题本质:判断一个序列是不是另一个序列的子序列。
基本解法:定义两个指针i、j分别指向s串和t串,遍历s串如果,则j++。这样的做法最坏的情况会遍历整个s串,虽然对于单次查询复杂度可以接受,但对于本题的多次查询显然不行。
贪心:如果在s串中有多个,那么肯定选用i值小的,因为i值小的可拓展性更好,或者说i值小的无法找到串t,则i值大的也无法找到。
问题关键:假设已经找到,如何快速的找到
?
预处理:从后往前遍历串s,并用数组记住每个字符最早出现的位置,并把
的值赋给
,这样找到
时可以直接跳到
。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const double pi = acos(-1);
const int mod = 1e9 + 7;
const double eps = 1e-8;
const int MAXN = 1e6 + 117;
const int MAXM = 2e5 + 117;
int n;
int to[MAXN][30], first[30];
char s[MAXN], t[MAXN];
bool solve() {
int len = strlen(t);
int id = first[t[0] - 'a'];
if(id == -1) return false;
for(int i = 1; i < len; i++) {
id = to[id][t[i] - 'a'];
if(id == -1) return false;
}
return true;
}
int main() {
scanf("%s", s);
scanf("%d", &n);
memset(first, -1, sizeof(first));
for(int i = strlen(s) - 1; i >= 0; i--) {
for(int j = 0; j < 30; j++) to[i][j] = first[j];
first[s[i] - 'a'] = i;
}
while(n--) {
scanf("%s", t);
if(solve()) puts("Yes");
else puts("No");
}
return 0;
} 
京公网安备 11010502036488号