牛客小白月赛12 J 月月查华华的手机 (序列自动机模板题)

时间:2021-12-14 18:48:39

链接:https://ac.nowcoder.com/acm/contest/392/J

来源:牛客网

题目描述

月月和华华一起去吃饭了。期间华华有事出去了一会儿,没有带手机。月月出于人类最单纯的好奇心,打开了华华的手机。哇,她看到了一片的QQ推荐好友,似乎华华还没有浏览过。月月顿时醋意大发,出于对好朋友的关心,为了避免华华浪费太多时间和其他网友聊天,她要删掉一些推荐好友。但是为了不让华华发现,产生猜疑,破坏了他们的友情,月月决定只删华华有可能搭讪的推荐好友。

月月熟知华华搭讪的规则。华华想与某个小姐姐搭讪,当且仅当小姐姐的昵称是他的昵称的子序列。为了方便,华华和小姐姐的昵称只由小写字母构成。为了更加方便,保证小姐姐的昵称长度不会比华华的长。

现在月月要快速的判断出哪些推荐好友要删掉,因为华华快回来了,时间紧迫,月月有点手忙脚乱,所以你赶紧写个程序帮帮她吧!

输入描述:

第一行输入一个字符串A表示华华的昵称。

第二行输入一个正整数N表示华华的推荐好友的个数。

接下来N行,每行输入一个字符串B_iB

i



表示某个推荐好友的昵称。

输出描述:

输出N行,对于第i个推荐好友,如果华华可能向她搭讪,输出Yes,否则输出No。

注意大写,同时也要注意输出效率对算法效率的影响。

示例1

输入

复制

noiauwfaurainairtqltqlmomomo

8

rain

air

tql

ntt

xiaobai

oiiiooo

orzcnzcnznb

ooooo

输出

复制

Yes

Yes

Yes

Yes

No

Yes

No

No

备注:

1\le|A|\le10^61≤∣A∣≤10

6

,1\le N\le10^61≤N≤10

6

,1\le\sum_{i=1}NB_i\le1061≤∑

i=1

N



B

i



≤10

6

思路:



本题是序列自动机模板题,

来讲解一下序列自动机是一个什么东西,

其实就是一个数组

nxt[ |str| ] [ |S| ] | str | 是字符串的最大长度, 而 | S | 是字符集合的元素个数。

我们对于母穿进行预处理 nxt数组,

nxt[i][j] 表示 第i个位置后面最近的j字符的下标。如果没有就是0。

获得的方法很简单,我们只需要从后向前扫一边类似dp的方法转移一下即可。

当一个子串来尝试匹配为母串的子序列时,只需要顺着nxt数组转移即可,当找不到需要的字符,即匹配到下标为0时(因为母串读入的时候从下标1开始读入字符),表示匹配失败。

返回失败即可。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/ int nxt[maxn][30];
char s[maxn];
int len;
void init()
{
for(int i=len;i>=1;--i)
{
for(int j=0;j<=25;++j)
{
nxt[i-1][j]=nxt[i][j];
}
nxt[i-1][s[i]-'a']=i;
}
}
char t[maxn];
int main()
{
//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout); scanf("%s",s+1);
len=strlen(s+1);
int q;
init();
scanf("%d",&q);
while(q--)
{
scanf("%s",t);
int len1=strlen(t);
int isok=1;
for(int now=0,i=0;i<len1;++i)
{
now=nxt[now][t[i]-'a'];
if(!now)
{
isok=0;
break;
}
}
if(isok)
{
puts("Yes");
}else
{
puts("No");
} } return 0;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
}
else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}