-
Notifications
You must be signed in to change notification settings - Fork 0
/
keyset.hpp
137 lines (108 loc) · 3.4 KB
/
keyset.hpp
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
#ifndef PLAIN_DA_TRIES__KEYSET_HPP_
#define PLAIN_DA_TRIES__KEYSET_HPP_
#include <cstdint>
#include <vector>
#include <string_view>
namespace plain_da {
class KeysetHandler {
public:
using value_type = std::string_view;
using iterator = std::vector<std::string_view>::iterator;
using const_iterator = std::vector<std::string_view>::const_iterator;
private:
std::vector<uint8_t> storage_;
std::vector<std::string_view> sv_list_;
std::vector<std::pair<size_t, size_t>> pls_;
public:
KeysetHandler() = default;
explicit KeysetHandler(std::istream& is) {
for (std::string key; std::getline(is, key); )
insert(key);
update_list();
}
void insert(std::string_view key) {
size_t front = storage_.size();
storage_.resize(storage_.size() + key.length()+1);
for (int i = 0; i < key.length(); i++)
storage_[front + i] = key[i];
storage_[front + key.length()] = '\0';
pls_.emplace_back(front, key.length());
}
void update_list() {
sv_list_.clear();
sv_list_.reserve(pls_.size());
for (auto [p, l] : pls_)
sv_list_.emplace_back((const char*) storage_.data() + p, l);
pls_ = {};
}
size_t size() const { return sv_list_.size(); }
std::string_view operator[](size_t i) const {
return sv_list_[i];
}
const_iterator begin() const { return sv_list_.begin(); }
const_iterator cbegin() const { return sv_list_.cbegin(); }
const_iterator end() const { return sv_list_.end(); }
const_iterator cend() const { return sv_list_.cend(); }
};
class RawTrie {
public:
static constexpr uint8_t kLeafChar = '\0';
struct Edge {
uint8_t c = kLeafChar;
int next = -1;
};
using TableType = std::vector<std::vector<Edge>>;
using const_iterator = TableType::const_iterator;
private:
TableType edge_table_;
public:
explicit RawTrie(const KeysetHandler& keyset) {
using key_iterator = typename KeysetHandler::const_iterator;
auto dfs = [&](
const auto dfs,
const key_iterator begin,
const key_iterator end,
int depth
) -> size_t {
size_t cur_node = edge_table_.size();
edge_table_.emplace_back();
assert(begin < end);
auto keyit = begin;
if (keyit->size() == depth) {
edge_table_[cur_node].push_back({kLeafChar, -1});
++keyit;
}
auto pit = keyit;
uint8_t pibot_char = kLeafChar;
while (keyit < end) {
uint8_t c = (*keyit)[depth];
if (pibot_char < c) {
if (pit < keyit) {
assert(!edge_table_[cur_node].empty());
edge_table_[cur_node].back().next = dfs(dfs, pit, keyit, depth+1);
}
edge_table_[cur_node].push_back({c, -1});
pit = keyit;
pibot_char = c;
}
++keyit;
}
if (pit < keyit) {
assert(!edge_table_[cur_node].empty());
edge_table_[cur_node].back().next = dfs(dfs, pit, keyit, depth+1);
}
return cur_node;
};
dfs(dfs, keyset.begin(), keyset.end(), 0);
}
size_t size() const { return edge_table_.size(); }
const std::vector<Edge>& operator[](size_t idx) const {
return edge_table_[idx];
}
const_iterator begin() const { return edge_table_.begin(); }
const_iterator cbegin() const { return edge_table_.cbegin(); }
const_iterator end() const { return edge_table_.end(); }
const_iterator cend() const { return edge_table_.cend(); }
};
}
#endif //PLAIN_DA_TRIES__KEYSET_HPP_