字典树

文章目录
原文地址:https://ngunauj.github.io

字典树,又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

字典树与字典很相似,当你要查一个单词是不是在字典树中,首先看单词的第一个字母是不是在字典的第一层,如果不在,说明字典树里没有该单词,如果在就在该字母的孩子节点里找是不是有单词的第二个字母,没有说明没有该单词,有的话用同样的方法继续查找.字典树不仅可以用来储存字母,也可以储存数字等其它数据。
Trie的数据结构定义:

1
2
3
4
5
6
7
8
9
10
11
class node {
public:
node* next[26];
int end;
node() {
for (int i = 0; i < 26; ++i) {
next[i] = nullptr;
}
end = 0;
}
};

next是表示每层有多少种类的数,如果只是小写字母,则26即可,若改为大小写字母,则是52,若再加上数字,则是62了,这里根据题意来确定。
end可以表示一个字典树到此有多少相同前缀的数目,这里根据需要应当学会自由变化。
Trie的查找(最主要的操作):
  (1) 每次从根结点开始一次搜索;
  (2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;  
  (3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。
  (4) 迭代过程……
  (5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。
  这里给出生成字典树和查找的代码:
这里面以208. Implement Trie (Prefix Tree)为例子给出字典树代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
class Trie {
public:
class node {
public:
node* next[26];
int end;
node() {
for (int i = 0; i < 26; ++i) {
next[i] = nullptr;
}
end = 0;
}
};
/** Initialize your data structure here. */
node* root;
Trie() {
root = new node();
}
/** Inserts a word into the trie. */
void insert(string word) {
if (word.size() == 0) return ;
node* p = root;
for (int i = 0; i < word.size(); ++i) {
int x = word[i] - 'a';
if (p->next[x] == nullptr) {
p->next[x] = new node();
p = p->next[x];
} else {
p = p->next[x];
}
}
p->end = 1;
}
/** Returns if the word is in the trie. */
bool search(string word) {
node* p = root;
for (int i = 0; i < word.size(); ++i) {
int x = word[i] - 'a';
if (p->next[x] != nullptr) {
p = p->next[x];
} else {
return false;
}
}
if (p->end == 1) return true;
return false;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
node* p = root;
for (int i = 0; i < prefix.size(); ++i) {
int x = prefix[i] - 'a';
if (p->next[x] != nullptr) {
p = p->next[x];
} else {
return false;
}
}
return true;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* bool param_2 = obj.search(word);
* bool param_3 = obj.startsWith(prefix);
*/

字典树还和dfs结合构造新的题目如leetcode 211. Add and Search Word - Data structure design
Design a data structure that supports the following two operations:
void addWord(word)
bool search(word)
search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter.

1
2
3
4
5
6
7
8
9
10
11
For example:
addWord("bad")
addWord("dad")
addWord("mad")
search("pad") -> false
search("bad") -> true
search(".ad") -> true
search("b..") -> true
Note:
You may assume that all words are consist of lowercase letters a-z.

思路:字典树+dfs时间复杂度 查询的时候复杂度O(26^n) n为‘.’的个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
class WordDictionary {
public:
/** Initialize your data structure here. */
WordDictionary() {
}
class node {
public:
node* next[26];
int end;
node() {
for (int i = 0; i < 26; ++i) {
next[i] = nullptr;
}
end = 0;
}
};
class Trie {
public:
node* root;
Trie() {
root = new node();
}
void add(string s) {
if (s.size() == 0) return ;
node* p = root;
for (int i = 0; i < s.size(); ++i) {
int x = s[i] - 'a';
if (p->next[x] == nullptr) {
p->next[x] = new node();
p = p->next[x];
} else {
p = p->next[x];
}
}
p->end = 1;
}
bool search(string& s, int pos, node *p) {
if (s.size() == pos && p->end == 1) {
return true;
}
if (s[pos] == '.') {
for (int j = 0; j < 26; ++j) {
if (p->next[j] != nullptr) {
if (search(s, pos + 1, p->next[j])) return true;
}
}
} else {
int x = (int)(s[pos] - 'a');
if (x >= 0 && x < 26 && p->next[x] != nullptr && search(s, pos + 1, p->next[x])) return true;
}
return false;
}
};
/** Adds a word into the data structure. */
void addWord(string word) {
ac.add(word);
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
bool search(string word) {
if (ac.search(word, 0, ac.root)) return true;
return false;
}
private:
Trie ac;
};
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary obj = new WordDictionary();
* obj.addWord(word);
* bool param_2 = obj.search(word);
*/

字典树还会有其他的应用,比如给你一些数字,再询问Q个问题,每个问题给一个数字,使这个数字和之前给出的数字的异或和最大。还有维护一个前缀树集合,进行字符串的查找,删除,添加等操作。


111x
欢迎关注:)

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
,