月月查华华的手机
https://ac.nowcoder.com/acm/problem/23053
https://ac.nowcoder.com/discuss/396686
题意:
输入一个字符串
A
A
A,一个整数
N
N
N,表示接下来有
N
N
N 个字符串
B
i
B_i
Bi,判断
B
i
B_i
Bi 是否为
A
A
A 的子序列。
思路:
暴力的话
O
(
∣
A
∣
⋅
∑
B
i
)
O(|A|·\sum B_i)
O(∣A∣⋅∑Bi),会 T。
n
e
x
t
[
i
]
[
′
a
′
.
.
.
′
z
′
]
next[i]['a'...'z']
next[i][′a′...′z′] 表示第
i
i
i 个位置往后的第一个'a'...'z'
出现的位置。
从后往前扫,用
l
a
s
t
[
′
a
′
.
.
.
′
z
′
]
last['a'...'z']
last[′a′...′z′] 维护当前位置往后第一个'a'...'z'
出现的位置,把
l
a
s
t
last
last 赋值给
n
e
x
t
[
i
]
next[i]
next[i] 即可。
Code:
#include <bits/stdc++.h>
#define mem(a, x) memset(a, x, sizeof(a))
using namespace std;
const int maxn = 1e6 + 5;
int n;
char s[maxn], t[maxn];
int nex[maxn][26], last[26];
void deal()
{
mem(last, -1);
int len = strlen(s);
for (int i = len - 1; i >= 0; i--)
{
memcpy(nex[i], last, sizeof(last));
last[s[i] - 'a'] = i;
}
}
bool check()
{
int len = strlen(t);
int i = last[t[0] - 'a'];
if (i == -1)
return false;
for (int j = 1; j < len; j++)
{
i = nex[i][t[j] - 'a'];
if (i == -1)
return false;
}
return true;
}
int main()
{
scanf("%s", s);
deal();
scanf("%d", &n);
while (n--)
{
scanf("%s", t);
if (check())
printf("Yes\n");
else
printf("No\n");
}
return 0;
}