题目描述
给定 N 个字符串 S1,S2,...,SN 和 M 个询问,每个询问包含一个字符串 Ti,问 Ti 是否在 S1 或 S2 ... 或 SN 的前缀出现过。
输入描述
输入第一行包含两个整数 N,M ,分别表示给定字符串的数量和询问的个数。
第 2∼N+1 行每行包含一个字符串 Si。
接下来 M 行每行包含一个字符串 Ti。
1≤N,M≤105。2≤∣S1+...+SN+T1+...+TM)∣≤2×106。
保证 Si,Ti 只包含小写字母。
输出描述
输出共 M 行,每行包含一个整数,表示对应询问的回答。
若存在则输出 Y,否则输出 N。
输入输出样例
示例 1
输入
5 3
aaa
aba
aabbaa
abbbbb
cdd
aabba
abc
abab
输出
Y
N
N
运行限制
- 最大运行时间:2s
- 最大运行内存: 512M
#include<iostream>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
const ll MAX = 2e6+10;
ll ch[MAX][27] = {0};
char s[MAX];
ll idx = 0;//动态编号
void insert()
{
int x = 0;
for (int i = 0; s[i] != '\0'; i++)
{
int j = (int)(s[i] - 'a');
if (ch[x][j] == 0)
{
ch[x][j] = ++idx;
}
x = ch[x][j];
}
}
bool check()
{
int x = 0;
for (int i = 0; s[i] != '\0'; i++)
{
int j = (int)(s[i] - 'a');
x = ch[x][j];
if (x == 0)
{
return false;
}
}
return true;
}
int main()
{
ll n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin>>s;
insert();
}
for (int i = 1; i <= m; i++)
{
cin >> s;
if (check())
{
cout << "Y" << endl;
}
else cout << "N" << endl;
}
return 0;
}
/*
* 先构建字典树
* ch[x][j]=w表示从x节点到w节点经过j+'a'字母
*/