Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 #include <emscripten/bind.h> | |
2 | |
3 using namespace emscripten; | |
4 | |
5 class CompactTrieNode { | |
6 public: | |
7 ~CompactTrieNode() { | |
8 CompactTrieNode* child = last_child; | |
9 | |
10 while (child) { | |
11 CompactTrieNode* sibling = child->previous_sibling; | |
12 delete child; | |
13 child = sibling; | |
14 } | |
15 } | |
16 | |
17 std::string bytes() const { | |
18 std::string str; | |
19 const CompactTrieNode* node = this; | |
20 | |
21 do { | |
22 str = node->key + str; | |
23 node = node->parent; | |
24 } while (node); | |
25 | |
26 return str; | |
27 } | |
28 | |
29 private: | |
30 std::string key; | |
31 int value = 0; | |
32 | |
33 CompactTrieNode* parent = nullptr; | |
34 CompactTrieNode* last_child = nullptr; | |
35 CompactTrieNode* previous_sibling = nullptr; | |
36 | |
37 friend class CompactTrie; | |
38 }; | |
39 | |
40 class CompactTrie { | |
41 public: | |
42 CompactTrie() {} | |
43 | |
44 CompactTrieNode* set(const std::string& key, int value) { | |
45 std::string key_ = key; | |
46 CompactTrieNode* node = &this->root; | |
47 | |
48 while (!key_.empty()) { | |
49 CompactTrieNode* child = node->last_child; | |
50 | |
51 while (child && child->key[0] != key_[0]) | |
52 child = child->previous_sibling; | |
53 | |
54 if (child) { | |
55 size_t n = std::max(child->key.length(), key_.length()); | |
Manish Jethani
2018/05/30 11:49:27
This should be std::min
| |
56 size_t i = 0; | |
Manish Jethani
2018/05/30 14:47:13
This could start at 1 instead of 0.
| |
57 | |
58 for (; i < n && child->key[i] == key_[i]; i++); | |
59 | |
60 if (i < child->key.length()) { | |
61 CompactTrieNode* grandchild = new CompactTrieNode(); | |
Manish Jethani
2018/05/30 14:47:13
Here we're basically splitting a child node into c
| |
62 grandchild->key = child->key.substr(i); | |
63 grandchild->last_child = child->last_child; | |
64 grandchild->parent = child; | |
65 | |
66 CompactTrieNode* great_grandchild = grandchild->last_child; | |
67 | |
68 while (great_grandchild) { | |
69 great_grandchild->parent = grandchild; | |
70 great_grandchild = great_grandchild->previous_sibling; | |
71 } | |
72 | |
73 child->key = child->key.substr(0, i); | |
74 child->last_child = grandchild; | |
75 } | |
76 | |
77 key_ = key_.substr(i); | |
78 | |
79 } else { | |
80 child = new CompactTrieNode(); | |
81 child->key = key_; | |
82 child->previous_sibling = node->last_child; | |
83 child->parent = node; | |
84 | |
85 node->last_child = child; | |
86 | |
87 key_.clear(); | |
88 } | |
89 | |
90 node = child; | |
91 } | |
92 | |
93 node->value = value; | |
94 return node; | |
95 } | |
96 | |
97 int get(const std::string& key) const { | |
98 std::string key_ = key; | |
99 const CompactTrieNode* node = &this->root; | |
100 | |
101 while (!key_.empty()) { | |
102 CompactTrieNode* child = node->last_child; | |
103 | |
104 while (child && child->key[0] != key_[0]) | |
105 child = child->previous_sibling; | |
106 | |
107 if (child) { | |
108 size_t n = std::max(child->key.length(), key_.length()); | |
Manish Jethani
2018/05/30 11:49:27
This should be std::min
| |
109 size_t i = 0; | |
Manish Jethani
2018/05/30 14:47:13
This could start at 1 instead of 0.
| |
110 | |
111 for (; i < n && child->key[i] == key_[i]; i++); | |
112 | |
113 if (i < child->key.length()) | |
114 return 0; | |
115 | |
116 key_ = key_.substr(i); | |
117 | |
118 } else { | |
119 return 0; | |
120 } | |
121 | |
122 node = child; | |
123 } | |
124 | |
125 return node->value; | |
126 } | |
127 | |
128 private: | |
129 CompactTrieNode root; | |
130 }; | |
131 | |
132 EMSCRIPTEN_BINDINGS(CompactTrieNode) { | |
133 class_<CompactTrieNode>("CompactTrieNode") | |
134 .function("bytes", &CompactTrieNode::bytes) | |
135 ; | |
136 } | |
137 | |
138 EMSCRIPTEN_BINDINGS(CompactTrie) { | |
139 class_<CompactTrie>("CompactTrie") | |
140 .constructor() | |
141 .function("set", &CompactTrie::set, allow_raw_pointers()) | |
142 .function("get", &CompactTrie::get) | |
143 ; | |
144 } | |
OLD | NEW |