-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path208-implement-trie-prefix-tree.cpp
152 lines (128 loc) · 5.41 KB
/
208-implement-trie-prefix-tree.cpp
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Title: Implement Trie (Prefix Tree)
// Description:
// A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings.
// There are various applications of this data structure, such as autocomplete and spellchecker.
// Implement the Trie class:
// - Trie() Initializes the trie object.
// - void insert(String word) Inserts the string word into the trie.
// - boolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.
// - boolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.
// Link: https://leetcode.com/problems/implement-trie-prefix-tree/
// Time complexity: O(n) for { insert(word), search(word), startsWith(prefix) }
// Space complexity: O(n)
class Trie {
private:
std::string key;
bool isWordEnd;
std::array<Trie *, 26> children;
public:
Trie() {
this->key = "";
this->isWordEnd = false;
std::fill(this->children.begin(), this->children.end(), nullptr);
}
void insert(std::string word) {
// if the word is empty
if (word == "") {
// mark the current node as a word end
this->isWordEnd = true;
return;
}
Trie *&childNode = this->children[word[0] - 'a'];
// if there is no child node for the word to go
if (childNode == NULL) {
// insert a new node with the word as the key
Trie *newNode = new Trie(); {
newNode->key = word;
newNode->isWordEnd = true;
}
childNode = newNode;
return;
}
std::string &childKey = childNode->key;
// find the end index of common prefix of the word and the child key
std::size_t matchEndIndex = 0;
while (
matchEndIndex != word.length() && matchEndIndex != childKey.length()
&& word[matchEndIndex] == childKey[matchEndIndex]
) ++matchEndIndex;
// if the child key is not full matched
if (matchEndIndex != childKey.length()) {
// split the prefix of the child key into a new node
Trie *newNode = new Trie(); {
newNode->key = childKey.substr(0, matchEndIndex);
newNode->children[childKey[matchEndIndex] - 'a'] = childNode;
}
childKey = childKey.substr(matchEndIndex, std::string::npos);
childNode = newNode;
}
// insert the remaining suffix of the word into the child node
childNode->insert(word.substr(matchEndIndex, std::string::npos));
}
bool search(std::string word) {
// if the word is empty
if (word == "") {
// the word is found if the current node is a word end
return this->isWordEnd;
}
Trie *&childNode = this->children[word[0] - 'a'];
// if there is no child node for the word to go
if (childNode == NULL) {
// the word cannot be found
return false;
}
std::string &childKey = childNode->key;
// find the end index of common prefix of the word and the child key
std::size_t matchEndIndex = 0;
while (
matchEndIndex != word.length() && matchEndIndex != childKey.length()
&& word[matchEndIndex] == childKey[matchEndIndex]
) ++matchEndIndex;
// if the child key is not full matched
if (matchEndIndex != childKey.length()) {
// the word cannot be found
return false;
}
// search the remaining suffix of the word from the child node
return childNode->search(word.substr(matchEndIndex, std::string::npos));
}
bool startsWith(std::string prefix) {
// if the prefix is empty
if (prefix == "") {
// the prefix is found
return true;
}
Trie *&childNode = this->children[prefix[0] - 'a'];
// if there is no child node for the prefix to go
if (childNode == NULL) {
// the prefix cannot be found
return false;
}
std::string &childKey = childNode->key;
// find the end index of common prefix of the prefix and the child key
std::size_t matchEndIndex = 0;
while (
matchEndIndex != prefix.length() && matchEndIndex != childKey.length()
&& prefix[matchEndIndex] == childKey[matchEndIndex]
) ++matchEndIndex;
// if the prefix is full matched
if (matchEndIndex == prefix.length()) {
// the prefix is found
return true;
}
// if the child key is not full matched
if (matchEndIndex != childKey.length()) {
// the prefix cannot be found
return false;
}
// search the remaining suffix of the prefix from the child node
return childNode->startsWith(prefix.substr(matchEndIndex, std::string::npos));
}
};
/**
* 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);
*/