:heavy_check_mark: Tree/trie.hpp

Verified with

Code

#include <bits/stdc++.h>
using namespace std;

template <class T>
struct Trie
{
    struct Node
    {
        unordered_map<T, int> next_node_ids;
        int pass_count = 0;
        int end_count = 0;

        Node() {};
    };

    vector<Node> nodes;
    Trie() : nodes()
    {
        nodes.push_back(Node());
    };

    template <typename Container>
        requires same_as<typename Container::value_type, T>
    void insert(const Container &v)
    {
        int node_id = 0;
        nodes[node_id].pass_count++;
        for (const auto &c : v)
        {
            if (!nodes[node_id].next_node_ids.contains(c))
            {
                nodes[node_id].next_node_ids[c] = nodes.size();
                nodes.push_back(Node());
            }

            node_id = nodes[node_id].next_node_ids[c];
            nodes[node_id].pass_count++;
        }

        nodes[node_id].end_count++;
    }

    template <typename Container, typename Func>
        requires same_as<typename Container::value_type, T> && invocable<Func, int, bool>
    void iterate_prefix(const Container &v, Func f)
    {
        int node_id = 0;
        for (auto itr = v.begin(); itr != v.end(); itr++)
        {
            if (!nodes[node_id].next_node_ids.contains(*itr))
            {
                return;
            }

            node_id = nodes[node_id].next_node_ids[*itr];
            f(node_id, next(itr) == v.end());
        }
    }

    template <typename Container>
        requires same_as<typename Container::value_type, T>
    void erase_subtrie(const Container &prefix)
    {
        int node_id = 0;
        vector<int> ancestors;
        for (const auto &c : prefix)
        {
            ancestors.push_back(node_id);
            if (!nodes[node_id].next_node_ids.contains(c))
            {
                return;
            }

            node_id = nodes[node_id].next_node_ids[c];
        }

        int removed_pass_count = nodes[node_id].pass_count;
        nodes[node_id].pass_count = 0, nodes[node_id].end_count = 0;
        nodes[node_id].next_node_ids.clear();

        for (const auto &ancestor : ancestors)
        {
            nodes[ancestor].pass_count -= removed_pass_count;
        }
    }
};
#line 1 "Tree/trie.hpp"
#include <bits/stdc++.h>
using namespace std;

template <class T>
struct Trie
{
    struct Node
    {
        unordered_map<T, int> next_node_ids;
        int pass_count = 0;
        int end_count = 0;

        Node() {};
    };

    vector<Node> nodes;
    Trie() : nodes()
    {
        nodes.push_back(Node());
    };

    template <typename Container>
        requires same_as<typename Container::value_type, T>
    void insert(const Container &v)
    {
        int node_id = 0;
        nodes[node_id].pass_count++;
        for (const auto &c : v)
        {
            if (!nodes[node_id].next_node_ids.contains(c))
            {
                nodes[node_id].next_node_ids[c] = nodes.size();
                nodes.push_back(Node());
            }

            node_id = nodes[node_id].next_node_ids[c];
            nodes[node_id].pass_count++;
        }

        nodes[node_id].end_count++;
    }

    template <typename Container, typename Func>
        requires same_as<typename Container::value_type, T> && invocable<Func, int, bool>
    void iterate_prefix(const Container &v, Func f)
    {
        int node_id = 0;
        for (auto itr = v.begin(); itr != v.end(); itr++)
        {
            if (!nodes[node_id].next_node_ids.contains(*itr))
            {
                return;
            }

            node_id = nodes[node_id].next_node_ids[*itr];
            f(node_id, next(itr) == v.end());
        }
    }

    template <typename Container>
        requires same_as<typename Container::value_type, T>
    void erase_subtrie(const Container &prefix)
    {
        int node_id = 0;
        vector<int> ancestors;
        for (const auto &c : prefix)
        {
            ancestors.push_back(node_id);
            if (!nodes[node_id].next_node_ids.contains(c))
            {
                return;
            }

            node_id = nodes[node_id].next_node_ids[c];
        }

        int removed_pass_count = nodes[node_id].pass_count;
        nodes[node_id].pass_count = 0, nodes[node_id].end_count = 0;
        nodes[node_id].next_node_ids.clear();

        for (const auto &ancestor : ancestors)
        {
            nodes[ancestor].pass_count -= removed_pass_count;
        }
    }
};
Back to top page