字典树Trie模版——字符串
程序员文章站
2022-05-19 18:55:05
...
教程
-
Trie树的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
-
Trie树有3个基本性质:
- 根节点不包含字符,除根节点外每一个节点都只包含一个字符
- 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串
- 每个节点的所有子节点包含的字符都不相同
复杂度
- 分析:在字典树中查询某个字符串s,查询时间复杂度仅与查询的深度有关,而在字典树中查询的深度 与 s的长度k有关,所以每次查询的复杂度为:
代码
#include<iostream>
#include<cstring>
using namespace std;
const int mx_node = 1e6 + 10;
const int mx_charset = 26;
int trie[mx_node][mx_charset];
int color[mx_node]; //存储是否是某个字符串结尾的标志
int k = 1; //默认根节点的编号是0,其他的节点的编号从1开始累加
void insert(char s[])
{
int ln = strlen(s), p = 0;
for(int i = 0; i < ln; i ++)
{
int c = s[i] - 'a';
if(! trie[p][c]) //当前节点不存在,我们添加一个新节点
trie[p][c] = k ++;
p = trie[p][c];
}
color[p] = 1; //标记 p 所指向的节点是字符串s的结尾
}
int search(char s[])
{
int ln = strlen(s), p = 0;
for(int i = 0; i < ln; i ++)
{
int c = s[i] - 'a';
if(! trie[p][c]) return 0;
p = trie[p][c];
}
return color[p] == 1;
}
int main()
{
int n, q;
scanf("%d %d", &n, &q);
char s[mx_node];
while(n --)
{
scanf("%s", s);
insert(s);
}
while(q --)
{
scanf("%s", s);
if(search(s))
printf("YES\n");
else
printf("NO\n");
}
/*
4 4
abb acd def eda
acd abbdf c edea
*/
return 0;
}