-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathTrieST.h
155 lines (121 loc) · 4.73 KB
/
TrieST.h
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
153
154
155
#ifndef TRIEST_H
#define TRIEST_H
#include <memory>
#include <optional>
#include <vector>
#include "StringST.h"
template<typename Value>
class TrieST : public StringST<Value> {
private:
inline static int R = 256; // radix
int N = 0;
struct Node {
std::optional<Value> val;
std::vector<std::unique_ptr<Node> > next = std::vector<std::unique_ptr<Node> >(R);
};
std::unique_ptr<Node> root;
const Node *get(const Node *x, std::string_view key, int d) const;
std::unique_ptr<Node> put(std::unique_ptr<Node> &x, std::string_view key, const Value &val, int d);
std::unique_ptr<Node> remove(std::unique_ptr<Node> &x, std::string_view key, int d);
void collect(const Node *x, const std::string &pre, std::list<std::string> &q) const;
void collect(const Node *x, const std::string &pre, std::string_view pat,
std::list<std::string> &q) const;
int search(const Node *x, std::string_view s, int d, int length) const;
public:
std::optional<Value> get(const std::string &key) const override;
void put(const std::string &key, const Value &val) override { root = put(root, key, val, 0); }
void remove(const std::string &key) override { root = remove(root, key, 0); }
int size() const override { return N; }
std::list<std::string> keys() const override { return keysWithPrefix(""); }
std::string longestPrefixOf(std::string_view s) const override;
std::list<std::string> keysWithPrefix(const std::string &pre) const override;
std::list<std::string> keysThatMatch(std::string_view pat) const override;
};
template<typename Value>
const typename TrieST<Value>::Node *TrieST<Value>::get(const Node *x, std::string_view key, int d) const {
if (!x) return nullptr;
if (d == key.length()) return x;
char c = key[d];
return get(x->next[c].get(), key, d + 1);
}
template<typename Value>
std::unique_ptr<typename TrieST<Value>::Node> TrieST<Value>::put(std::unique_ptr<Node> &x, std::string_view key,
const Value &val, int d) {
if (!x) x = std::make_unique<Node>();
if (d == key.length()) {
if (!x->val) ++N;
x->val = val;
return std::move(x);
}
char c = key[d];
x->next[c] = put(x->next[c], key, val, d + 1);
return std::move(x);
}
template<typename Value>
std::unique_ptr<typename TrieST<Value>::Node> TrieST<Value>::remove(std::unique_ptr<Node> &x, std::string_view key,
int d) {
if (!x) return nullptr;
if (d == key.length()) {
if (x->val) --N;
x->val = std::nullopt;
} else {
char c = key[d];
x->next[c] = remove(x->next[c], key, d + 1);
}
// Remove subtrie rooted at x if it is completely empty.
if (x->val) return std::move(x);
for (int c = 0; c < R; ++c) {
if (x->next[c]) return std::move(x);
}
return nullptr;
}
template<typename Value>
void TrieST<Value>::collect(const Node *x, const std::string &pre, std::list<std::string> &q) const {
if (!x) return;
if (x->val) q.push_back(pre);
for (int c = 0; c < R; ++c) collect(x->next[c].get(), pre + static_cast<char>(c), q);
}
template<typename Value>
void TrieST<Value>::collect(const Node *x, const std::string &pre, std::string_view pat,
std::list<std::string> &q) const {
if (!x) return;
int d = pre.length();
if (d == pat.length() && x->val) q.push_back(pre);
if (d == pat.length()) return;
char next = pat[d];
for (int c = 0; c < R; ++c) {
if (next == '.' || next == c) collect(x->next[c].get(), pre + static_cast<char>(c), pat, q);
}
}
template<typename Value>
int TrieST<Value>::search(const Node *x, std::string_view s, int d, int length) const {
if (!x) return length;
if (x->val) length = d;
if (d == s.length()) return length;
char c = s[d];
return search(x->next[c].get(), s, d + 1, length);
}
template<typename Value>
std::optional<Value> TrieST<Value>::get(const std::string &key) const {
const Node *x = get(root.get(), key, 0);
if (!x) return std::nullopt;
return x->val;
}
template<typename Value>
std::string TrieST<Value>::longestPrefixOf(std::string_view s) const {
int length = search(root.get(), s, 0, 0);
return std::string(s.substr(0, length));
}
template<typename Value>
std::list<std::string> TrieST<Value>::keysWithPrefix(const std::string &pre) const {
std::list<std::string> q;
collect(get(root.get(), pre, 0), pre, q);
return q;
}
template<typename Value>
std::list<std::string> TrieST<Value>::keysThatMatch(std::string_view pat) const {
std::list<std::string> q;
collect(root.get(), "", pat, q);
return q;
}
#endif //TRIEST_H