library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub kk2a/library

:warning: others/multiset_hash.hpp

Code

#ifndef KK2_OTHERS_MULTISET_HASH_HPP
#define KK2_OTHERS_MULTISET_HASH_HPP 1

#include <algorithm>
#include <array>
#include <ctime>
#include <iostream>
#include <random>
#include <unordered_map>

namespace kk2 {

template <typename T> struct MultiSetHash {
    constexpr static int b = 5;
    constexpr static int modp[b] = {998244353, 1000000007, 1000000009, 1000000021, 1000000033};
    using Hashs = std::array<long long, b>;
    int siz;
    Hashs table;
    static std::mt19937_64 rng;
    static std::unordered_map<T, Hashs> base;

    static Hashs getbase(const T &x) {
        if (base.count(x)) return base[x];
        base[x] = Hashs();
        for (int i = 0; i < b; ++i) { base[x][i] = rng() % modp[i]; }
        return base[x];
    }

    MultiSetHash() : siz(0) { std::fill(std::begin(table), std::end(table), 0); }

    MultiSetHash(const T &x) : siz(1) { table = getbase(x); }

    MultiSetHash(const std::vector<T> &v) : siz(v.size()) {
        for (int i = 0; i < siz; i++) {
            auto tmp = getbase(v[i]);
            for (int j = 0; j < b; ++j) { table[j] = (table[j] + tmp[j]) % modp[j]; }
        }
    }

    MultiSetHash &merge(const MultiSetHash &rhs) {
        for (int i = 0; rhs.siz; ++i) { table[i] = (table[i] + rhs.table[i]) % modp[i]; }
        siz += rhs.siz;
        return *this;
    }

    MultiSetHash &merge(const T &x) {
        auto tmp = getbase(x);
        for (int i = 0; i < b; ++i) { table[i] = (table[i] + tmp[i]) % modp[i]; }
        siz++;
        return *this;
    }

    // require: rhs \subset *this
    MultiSetHash &erase(const MultiSetHash &rhs) {
        for (int i = 0; i < b; ++i) { table[i] = (table[i] - rhs.table[i] + modp[i]) % modp[i]; }
        siz -= rhs.siz;
        return *this;
    }

    // require: x \in *this
    MultiSetHash &erase(const T &x) {
        auto tmp = getbase(x);
        for (int i = 0; i < b; ++i) { table[i] = (table[i] - tmp[i] + modp[i]) % modp[i]; }
        siz--;
        return *this;
    }

    friend MultiSetHash merge(const MultiSetHash &lhs, const MultiSetHash &rhs) {
        return MultiSetHash(lhs).merge(rhs);
    }

    friend MultiSetHash merge(const MultiSetHash &lhs, const T &x) {
        return MultiSetHash(lhs).merge(x);
    }

    friend MultiSetHash erase(const MultiSetHash &lhs, const MultiSetHash &rhs) {
        return MultiSetHash(lhs).erase(rhs);
    }

    friend MultiSetHash erase(const MultiSetHash &lhs, const T &x) {
        return MultiSetHash(lhs).erase(x);
    }

    friend bool operator==(const MultiSetHash &lhs, const MultiSetHash &rhs) {
        return lhs.table == rhs.table && lhs.siz == rhs.siz;
    }

    friend bool operator!=(const MultiSetHash &lhs, const MultiSetHash &rhs) {
        return lhs.table != rhs.table || lhs.siz != rhs.siz;
    }

    friend std::ostream &operator<<(std::ostream &os, const MultiSetHash &msh) {
        os << "siz: " << msh.siz << " table: ";
        for (int i = 0; i < b; ++i) { os << msh.table[i] << " "; }
        os << "\n";
        return os;
    }
};

template <typename T> std::unordered_map<T, typename MultiSetHash<T>::Hashs> MultiSetHash<T>::base;

template <typename T> std::mt19937_64 MultiSetHash<T>::rng(time(0));

} // namespace kk2

#endif // KK2_OTHERS_MULTISET_HASH_HPP
#line 1 "others/multiset_hash.hpp"



#include <algorithm>
#include <array>
#include <ctime>
#include <iostream>
#include <random>
#include <unordered_map>

namespace kk2 {

template <typename T> struct MultiSetHash {
    constexpr static int b = 5;
    constexpr static int modp[b] = {998244353, 1000000007, 1000000009, 1000000021, 1000000033};
    using Hashs = std::array<long long, b>;
    int siz;
    Hashs table;
    static std::mt19937_64 rng;
    static std::unordered_map<T, Hashs> base;

    static Hashs getbase(const T &x) {
        if (base.count(x)) return base[x];
        base[x] = Hashs();
        for (int i = 0; i < b; ++i) { base[x][i] = rng() % modp[i]; }
        return base[x];
    }

    MultiSetHash() : siz(0) { std::fill(std::begin(table), std::end(table), 0); }

    MultiSetHash(const T &x) : siz(1) { table = getbase(x); }

    MultiSetHash(const std::vector<T> &v) : siz(v.size()) {
        for (int i = 0; i < siz; i++) {
            auto tmp = getbase(v[i]);
            for (int j = 0; j < b; ++j) { table[j] = (table[j] + tmp[j]) % modp[j]; }
        }
    }

    MultiSetHash &merge(const MultiSetHash &rhs) {
        for (int i = 0; rhs.siz; ++i) { table[i] = (table[i] + rhs.table[i]) % modp[i]; }
        siz += rhs.siz;
        return *this;
    }

    MultiSetHash &merge(const T &x) {
        auto tmp = getbase(x);
        for (int i = 0; i < b; ++i) { table[i] = (table[i] + tmp[i]) % modp[i]; }
        siz++;
        return *this;
    }

    // require: rhs \subset *this
    MultiSetHash &erase(const MultiSetHash &rhs) {
        for (int i = 0; i < b; ++i) { table[i] = (table[i] - rhs.table[i] + modp[i]) % modp[i]; }
        siz -= rhs.siz;
        return *this;
    }

    // require: x \in *this
    MultiSetHash &erase(const T &x) {
        auto tmp = getbase(x);
        for (int i = 0; i < b; ++i) { table[i] = (table[i] - tmp[i] + modp[i]) % modp[i]; }
        siz--;
        return *this;
    }

    friend MultiSetHash merge(const MultiSetHash &lhs, const MultiSetHash &rhs) {
        return MultiSetHash(lhs).merge(rhs);
    }

    friend MultiSetHash merge(const MultiSetHash &lhs, const T &x) {
        return MultiSetHash(lhs).merge(x);
    }

    friend MultiSetHash erase(const MultiSetHash &lhs, const MultiSetHash &rhs) {
        return MultiSetHash(lhs).erase(rhs);
    }

    friend MultiSetHash erase(const MultiSetHash &lhs, const T &x) {
        return MultiSetHash(lhs).erase(x);
    }

    friend bool operator==(const MultiSetHash &lhs, const MultiSetHash &rhs) {
        return lhs.table == rhs.table && lhs.siz == rhs.siz;
    }

    friend bool operator!=(const MultiSetHash &lhs, const MultiSetHash &rhs) {
        return lhs.table != rhs.table || lhs.siz != rhs.siz;
    }

    friend std::ostream &operator<<(std::ostream &os, const MultiSetHash &msh) {
        os << "siz: " << msh.siz << " table: ";
        for (int i = 0; i < b; ++i) { os << msh.table[i] << " "; }
        os << "\n";
        return os;
    }
};

template <typename T> std::unordered_map<T, typename MultiSetHash<T>::Hashs> MultiSetHash<T>::base;

template <typename T> std::mt19937_64 MultiSetHash<T>::rng(time(0));

} // namespace kk2
Back to top page