#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <set>
class Node
{
public:
bool endOfSentence = false;
std::set<int> weights;
std::map<std::string, Node> children;
Node() = default;
const Node* get(const std::string& word) const
{
auto it = children.find(word);
if (it == children.end()) {
return nullptr;
}
return &it->second;
}
auto find_by_weight(int weight) const
{
return std::find_if(children.begin(),
children.end(),
[=](const auto& p){ return p.second.weights.count(weight);});
}
};
class Trie
{
Node root;
public:
void add(int weight, const std::vector<std::string>& phrase)
{
Node* node = &root;
for (const auto& word : phrase) {
node->weights.insert(weight);
node = &node->children[word];
}
node->weights.insert(weight);
node->endOfSentence = true;
}
bool contains(const std::vector<std::string>& phrase) const
{
const Node* node = &root;
for (const auto& word : phrase) {
node = node->get(word);
if (node == nullptr) {
return false;
}
}
return node->endOfSentence;
}
void print(int weight) const
{
const Node* node = &root;
const char* sep = "";
while (node) {
const auto it = node->find_by_weight(weight);
if (it == node->children.end()) {
break;
}
std::cout << sep << it->first;
sep = " ";
node = &it->second;
}
std::cout << std::endl;
}
void print_all() const
{
for (int i : root.weights) {
print(i);
}
}
};
int main(int argc, char* argv[]) {
const std::vector<std::vector<std::string>> sentences = {
{"My", "name", "is", "John"},
{"My", "house", "is", "small"},
{"Hello", "world"},
{"Hello", "world", "!"}
};
Trie trie;
int i = 0;
for (const auto& sentence : sentences) {
trie.add(i, sentence);
++i;
}
const std::vector<std::vector<std::string>> queries = {
{"My", "name", "is", "John"},
{"My", "house"},
{"Hello", "world"}
};
for (const auto& query : queries) {
std::cout << trie.contains(query) << std::endl;
}
trie.print_all();
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8c2V0PgoKY2xhc3MgTm9kZQp7CnB1YmxpYzoKICAgIGJvb2wgZW5kT2ZTZW50ZW5jZSA9IGZhbHNlOwogICAgc3RkOjpzZXQ8aW50PiB3ZWlnaHRzOwogICAgc3RkOjptYXA8c3RkOjpzdHJpbmcsIE5vZGU+IGNoaWxkcmVuOwoKICAgIE5vZGUoKSA9IGRlZmF1bHQ7CiAgICAKICAgIGNvbnN0IE5vZGUqIGdldChjb25zdCBzdGQ6OnN0cmluZyYgd29yZCkgY29uc3QKICAgIHsKICAgICAgICBhdXRvIGl0ID0gY2hpbGRyZW4uZmluZCh3b3JkKTsKICAgICAgICAKICAgICAgICBpZiAoaXQgPT0gY2hpbGRyZW4uZW5kKCkpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGxwdHI7ICAgCiAgICAgICAgfQogICAgICAgIHJldHVybiAmaXQtPnNlY29uZDsKICAgIH0KICAgIAogICAgYXV0byBmaW5kX2J5X3dlaWdodChpbnQgd2VpZ2h0KSBjb25zdAogICAgewogICAgICAgIHJldHVybiBzdGQ6OmZpbmRfaWYoY2hpbGRyZW4uYmVnaW4oKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuLmVuZCgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgWz1dKGNvbnN0IGF1dG8mIHApeyByZXR1cm4gcC5zZWNvbmQud2VpZ2h0cy5jb3VudCh3ZWlnaHQpO30pOwogICAgfQoKfTsKCgpjbGFzcyBUcmllCnsKICAgIE5vZGUgcm9vdDsKcHVibGljOgoKICAgIHZvaWQgYWRkKGludCB3ZWlnaHQsIGNvbnN0IHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiYgcGhyYXNlKQogICAgewogICAgICAgIE5vZGUqIG5vZGUgPSAmcm9vdDsKICAgICAgICBmb3IgKGNvbnN0IGF1dG8mIHdvcmQgOiBwaHJhc2UpIHsKICAgICAgICAgICAgbm9kZS0+d2VpZ2h0cy5pbnNlcnQod2VpZ2h0KTsKICAgICAgICAgICAgbm9kZSA9ICZub2RlLT5jaGlsZHJlblt3b3JkXTsKICAgICAgICB9CiAgICAgICAgbm9kZS0+d2VpZ2h0cy5pbnNlcnQod2VpZ2h0KTsKICAgICAgICBub2RlLT5lbmRPZlNlbnRlbmNlID0gdHJ1ZTsKICAgIH0KCiAgICBib29sIGNvbnRhaW5zKGNvbnN0IHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiYgcGhyYXNlKSBjb25zdAogICAgewogICAgICAgIGNvbnN0IE5vZGUqIG5vZGUgPSAmcm9vdDsKICAgICAgICBmb3IgKGNvbnN0IGF1dG8mIHdvcmQgOiBwaHJhc2UpIHsKICAgICAgICAgICAgbm9kZSA9IG5vZGUtPmdldCh3b3JkKTsKICAgICAgICAgICAgaWYgKG5vZGUgPT0gbnVsbHB0cikgewogICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBub2RlLT5lbmRPZlNlbnRlbmNlOwogICAgfQoKICAgIHZvaWQgcHJpbnQoaW50IHdlaWdodCkgY29uc3QKICAgIHsKICAgICAgICBjb25zdCBOb2RlKiBub2RlID0gJnJvb3Q7CiAgICAgICAgY29uc3QgY2hhciogc2VwID0gIiI7CiAgICAgICAgd2hpbGUgKG5vZGUpIHsKICAgICAgICAgICAgY29uc3QgYXV0byBpdCA9IG5vZGUtPmZpbmRfYnlfd2VpZ2h0KHdlaWdodCk7CgogICAgICAgICAgICBpZiAoaXQgPT0gbm9kZS0+Y2hpbGRyZW4uZW5kKCkpIHsKICAgICAgICAgICAgCWJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN0ZDo6Y291dCA8PCBzZXAgPDwgaXQtPmZpcnN0OwogICAgICAgICAgICBzZXAgPSAiICI7CiAgICAgICAgICAgIG5vZGUgPSAmaXQtPnNlY29uZDsKICAgICAgICB9CiAgICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKICAgIH0KCiAgICB2b2lkIHByaW50X2FsbCgpIGNvbnN0CiAgICB7CiAgICAgICAgZm9yIChpbnQgaSA6IHJvb3Qud2VpZ2h0cykgewogICAgICAgICAgICBwcmludChpKTsgICAKICAgICAgICB9CiAgICB9Cn07CgppbnQgbWFpbihpbnQgYXJnYywgY2hhciogYXJndltdKSB7CiAgICBjb25zdCBzdGQ6OnZlY3RvcjxzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4+IHNlbnRlbmNlcyA9IHsKICAgICAgICB7Ik15IiwgIm5hbWUiLCAiaXMiLCAiSm9obiJ9LAogICAgICAgIHsiTXkiLCAiaG91c2UiLCAiaXMiLCAic21hbGwifSwKICAgICAgICB7IkhlbGxvIiwgIndvcmxkIn0sCiAgICAgICAgeyJIZWxsbyIsICJ3b3JsZCIsICIhIn0KICAgIH07CgogICAgVHJpZSB0cmllOwogICAgaW50IGkgPSAwOwogICAgZm9yIChjb25zdCBhdXRvJiBzZW50ZW5jZSA6IHNlbnRlbmNlcykgewogICAgICAgIHRyaWUuYWRkKGksIHNlbnRlbmNlKTsKICAgICAgICArK2k7CiAgICB9CgogICAgY29uc3Qgc3RkOjp2ZWN0b3I8c3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+PiBxdWVyaWVzID0gewogICAgICAgIHsiTXkiLCAibmFtZSIsICJpcyIsICJKb2huIn0sCiAgICAgICAgeyJNeSIsICJob3VzZSJ9LAogICAgICAgIHsiSGVsbG8iLCAid29ybGQifQogICAgfTsKCiAgICBmb3IgKGNvbnN0IGF1dG8mIHF1ZXJ5IDogcXVlcmllcykgewogICAgICAgIHN0ZDo6Y291dCA8PCB0cmllLmNvbnRhaW5zKHF1ZXJ5KSA8PCBzdGQ6OmVuZGw7CiAgICB9CgogICAgdHJpZS5wcmludF9hbGwoKTsKfQo=