题目描述
Description
最经,skyzhong得到了一本好厉害的字典,这个字典里整整有n个单词(1<=n<=200000)
现在skyzhong需要在字典里查询以某一段字母开头的单词
如:skyzhong想查询a
那么只要是a开头的单词就可以了
skyzhong只想知道里面有没有这一个单词(因为没有他就不查了)
若有,请输出YES。若没有,请输出NO
输入描述
Input Description
第一行一个数n
第二行到第n+1行,一行一个字符串
再下一行一个数m,表示skyzhong想要查询的次数
接着m行,一行一个字符串,表示skyzhong想要查的东西
输出描述
Output Description
共m行,若有这字串输出YES,否则输出NO
样例输入
Sample Input
3
asd
asfdghj
asfd
3
asd
asdghj
asf
样例输出
Sample Output
YES
NO
YES
数据范围及提示
Data Size & Hint
字符串只有小写字母,且长度≤8
代码:
#include<bits/stdc++.h>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
const int maxn = 1e6+7;
int trie[maxn][27], tot = 0;
bool isw[maxn]; //标记单词结束的结点i
int sum[maxn]; //保存前缀出现的次数
void rinsert(string s) //插入单词s
{
int len = s.length(), root = 0; //根节点编号为0;
for(int i = 0; i < len; i++) {
int id = s[i] - 'a'; //第一种编号j
if(!trie[root][id]) //如果之前没有root到id的前缀
trie[root][id] = ++tot; //插入,tot即为第一种编号
//sum[trie[root][id]]++; //前缀后一个位置保存前缀出现的次数;
root = trie[root][id]; //顺着字典树往下走
}
/*isw[root] = true; 标记单词结束的结点*/
}
int rsearch(string s) {
int len = s.length(), root = 0; //从跟节点开始查找;
for(int i = 0; i < len; i++) {
int id = s[i] - 'a';
if(!trie[root][id]) return false; //从root到id的前缀不存在,返回false
root = trie[root][id]; //为查询下一个字母,顺着字典树往下走
}
return true; //存在返回true
//return isw[root]; 查询整个单词是返回isw[root];
//return sum[root]; //前缀后一个位置保存前缀出现的次数;返回值需改为int;
}
int main()
{
memset(isw, 0, sizeof(isw));
memset(sum, 0, sizeof(sum));
string s;
int n;
scanf("%d",&n);
while(n--)
{
cin >> s;
rinsert(s);
}
scanf("%d", &n);
while(n--)
{
cin >> s;
if(rsearch(s)) puts("YES");
else puts("NO");
}
return 0;
}