前缀树

前缀树

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <unordered_map>
using namespace std;

class TrieNode
{
public:
int pass;
int end;

// 当字符种类非常多的时候(例如java中有六万多字符)
// 这个时候再去采用定长的数组显然不合适
// 可以采用hashmap来存放字符和node
// unordered_map<char, shared_ptr<TrieNode>> nexts;
vector<shared_ptr<TrieNode>> nexts;

public:
TrieNode()
{
pass = 0;
end = 0;
// nexts[0] == nullptr, 没有走向'a'的路
// nexts[0] != nullptr, 有走向'a'的路
// ...
// nexts[25] != nullptr
nexts.resize(26, nullptr);
}
~TrieNode()
{
nexts.clear();
}
};

class Trie
{
public:
shared_ptr<TrieNode> root;
Trie()
{
root = make_shared<TrieNode>();
}
void insert(string word)
{
TrieNode *node = root.get();
node->pass++;
int index = 0;
for (int i = 0; i < word.length(); i++)
{
index = word[i] - 'a';
if (node->nexts[index] == nullptr)
{
node->nexts[index] = make_shared<TrieNode>();
}
node = node->nexts[index].get();
node->pass++;
}
node->end++;
}

// word这个单词之前加入过几次
int search(string word)
{
TrieNode *node = root.get();
int index = 0;
for (int i = 0; i < word.length(); i++)
{
index = word[i] - 'a';
if (node->nexts[index] == nullptr)
{
return 0;
}
node = node->nexts[index].get();
}
return node->end;
}

// 删除一个单词
void deleteWord(string word)
{
if (search(word) != 0)
{
TrieNode *node = root.get();
node->pass--;
int index = 0;
for (int i = 0; i < word.length(); i++)
{
index = word[i] - 'a';
if (--node->nexts[index].get()->pass == 0)
{
// 从当前已知p节点遍历到底去析构
shared_ptr<TrieNode> cur = node->nexts[index];
node->nexts[index].reset();
node->nexts[index] = nullptr;
i++;
while (node != nullptr && i < word.length())
{
node = cur->nexts[word[i] - 'a'].get();
node->nexts[index].reset();
node->nexts[index] = nullptr;
cur = cur->nexts[word[++i] - 'a'];
}
return;
}
node = node->nexts[index].get();
}
}
}

// 所有加入的字符串中,有几个是以pre这个字符串作为前缀的
int prefixNumber(string pre)
{
TrieNode *node = root.get();
int index = 0;
for (int i = 0; i < pre.length(); i++)
{
index = pre[index] - 'a';
if (node->nexts[index] == nullptr)
{
return 0;
}
node = node->nexts[index].get();
}
return node->pass;
}
};

int main()
{
Trie t;
t.insert("abc");

return 0;
}

前缀树
http://example.com/2023/08/29/前缀树/
作者
WHC
发布于
2023年8月29日
许可协议