【模板】子序列自动机
题目链接:luogu P5826
题目大意
给你一个序列,每次再给你一个序列,问你新的序列是不是一开始的序列的子序列。
思路
如果字符少不难想象到一个 \(f_{i,j}\) 表示 \(i\) 这个位置开始第一个字符是 \(j\) 的位置,然后直接走看看行不行。
但是字符多,于是考虑用时间换空间。
考虑用 vector 记录每个字符在哪些位置出现。
那把每个 vector 排序一下之后你就可以通过二分(lower_bound)找到你当前位置下一个要的字符最近在哪里。
然后就好了。
代码
#include<cstdio>
#include<vector>
using namespace std;
const int N = 1e5 + 100;
const int M = 1e6 + 100;
int type, n, q, m, a[N];
int sz, b[M];
vector <int> f[N];
int main() {
scanf("%d %d %d %d", &type, &n, &q, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), f[a[i]].push_back(i);
while (q--) {
scanf("%d", &sz); for (int i = 1; i <= sz; i++) scanf("%d", &b[i]);
int now = 0;
for (int i = 1; i <= sz && now <= n; i++) {
vector <int>::iterator it = lower_bound(f[b[i]].begin(), f[b[i]].end(), now + 1);
if (it == f[b[i]].end()) now = n + 1;
else now = *it;
}
if (now <= n) printf("Yes\n");
else printf("No\n");
}
return 0;
}
标签:字符,int,luogu,vector,P5826,序列,now,模板
From: https://www.cnblogs.com/Sakura-TJH/p/luogu_P5826.html