-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimplement_trie.cpp
More file actions
151 lines (126 loc) · 3.52 KB
/
implement_trie.cpp
File metadata and controls
151 lines (126 loc) · 3.52 KB
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
// 208. Implement Trie: https://leetcode.com/problems/implement-trie-prefix-tree
// Author: xianfeng.zhu@gmail.com
#include <string>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using std::string;
using std::vector;
// Use std::string
class Trie1 {
public:
/** Initialize your data structure here. */
Trie1() { value_ = " "; }
/** Inserts a word into the trie. */
void insert(const string& word) { value_ += word + " "; }
/** Returns if the word is in the trie. */
bool search(const string& word) { return (value_.find(" " + word + " ") != string::npos); }
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(const string& prefix) { return (value_.find(" " + prefix) != string::npos); }
private:
string value_;
};
// Implement prefix tree
class Trie2 {
struct Node {
// Children's indices
Node* children[26] = {nullptr};
bool is_end = false;
};
public:
/** Initialize your data structure here. */
Trie2() { root_ = new Node(); }
/** Inserts a word into the trie. */
void insert(const string& word) {
Node* ptr = root_;
for (const auto chr : word) {
if (ptr->children[chr - 'a'] == nullptr) {
ptr->children[chr - 'a'] = new Node();
}
ptr = ptr->children[chr - 'a'];
}
ptr->is_end = true;
}
/** Returns if the word is in the trie. */
bool search(const string& word) {
const auto* node = find(word);
return (node != nullptr && node->is_end);
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(const string& prefix) {
const auto* node = find(prefix);
return (node != nullptr);
}
private:
const Node* find(const string& word) {
Node* ptr = root_;
for (const auto chr : word) {
if (ptr->children[chr - 'a'] == nullptr) {
return nullptr;
}
ptr = ptr->children[chr - 'a'];
}
return ptr;
}
private:
Node* root_;
};
// Implement prefix tree with vector
class Trie3 {
struct Node {
// Children's indices
int indices[26] = {};
bool is_end = false;
};
public:
/** Initialize your data structure here. */
Trie3() : nodes_(1, Node()) {}
/** Inserts a word into the trie. */
void insert(const string& word) {
int idx = 0;
for (const auto chr : word) {
if (nodes_[idx].indices[chr - 'a'] == 0) {
// Append new node to the end
nodes_.emplace_back();
nodes_[idx].indices[chr - 'a'] = nodes_.size() - 1;
idx = nodes_.size() - 1;
} else {
idx = nodes_[idx].indices[chr - 'a'];
}
}
nodes_[idx].is_end = true;
}
/** Returns if the word is in the trie. */
bool search(const string& word) {
const auto* node = find(word);
return (node != nullptr && node->is_end);
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(const string& prefix) {
const auto* node = find(prefix);
return (node != nullptr);
}
private:
const Node* find(const string& word) {
int idx = 0;
for (const auto chr : word) {
idx = nodes_[idx].indices[chr - 'a'];
if (idx == 0) {
return nullptr;
}
}
return &nodes_[idx];
}
private:
vector<Node> nodes_;
};
using Trie = Trie2;
TEST(Solution, Trie) {
Trie trie;
trie.insert("apple");
EXPECT_EQ(trie.search("apple"), true);
EXPECT_EQ(trie.search("app"), false);
EXPECT_EQ(trie.startsWith("app"), true);
trie.insert("app");
EXPECT_EQ(trie.search("app"), true);
}