目录
目录
一、定义:
字典树又称Trie树,是哈希树的一种变种,主要用于统计、排序、存储大量字符串。
二、原理:
可以发现,这棵字典树用边来代表字母,而从根结点到树上某一结点的路径就代表了一个字符串。举个例子, 表示的就是字符串 caa
。
trie 的结构非常好懂,我们用 表示结点 的 字符指向的下一个结点,或着说是结点 代表的字符串后面添加一个字符 形成的字符串的结点。( 的取值范围和字符集大小有关,不一定是 。)
有时需要标记插入进 trie 的是哪些字符串,每次插入完成时在这个字符串所代表的节点处打上标记即可。
每个节点包含多个字符指针,将从根节点到某一节点路径上经过的字符连接起来,为该节点对应的字符串。在单词结束位置可增设一个变量end[]标记,表示从根节点到此节点有一个整个单词。
字典树的基本性质如下:
- 根节点没有字符路径。除根节点外,每一个节点都被一个字符路径找到;
- 从根节点出发到任何一个节点,如果将沿途经过的字符连接起来,一定为某个加入过的字符串的前缀;
- 每个节点向下的所有字符串路径上的字符都不同;
基本操作:创建(插入)、查找、删除
优点:
利用字符串的公共前缀来减少查询时间,最大限度减少无谓的字符串的比较,效率比哈系数高。
数据结构:数组或链表
若单词总长度为N,字符的种类为k,插入字符串长度为n则:
创建复杂度:O(N)
空间复杂度:O(Nk)
插入时间复杂度:O(n)
查找字符串时间复杂度:O(n)
三、算法代码:
// C++ Version
struct trie {
int nex[100000][26], cnt;
bool exist[100000]; // 该结点结尾的字符串是否存在
void insert(char *s, int l) { // 插入字符串
int p = 0;
for (int i = 0; i < l; i++) {
int c = s[i] - 'a';
if (!nex[p][c]) nex[p][c] = ++cnt; // 如果没有,就添加结点
p = nex[p][c];
}
exist[p] = 1;
}
bool find(char *s, int l) { // 查找字符串
int p = 0;
for (int i = 0; i < l; i++) {
int c = s[i] - 'a';
if (!nex[p][c]) return 0;
p = nex[p][c];
}
return exist[p];
}
};
四、例题: