:warning: Zobrist Hash (集合) (Hash/zobrist_type_hash.hpp)

ZobristTypeHash

ZobristTypeHash は、Zobrist Hash を用いて指定範囲の数値列に含まれる 数値の集合 のハッシュ値を計算するクラスです。

コンストラクタ

ZobristTypeHash(const vector<long long>& v)

数値列 v 全体の累積ハッシュを初期化します。

計算量

  • $O(N)$

get_range_hash

unsigned long long get_range_hash(int l, int r)

指定された範囲 [l, r) の数値列に含まれる要素の累積ハッシュ値を返します。

制約

  • $\color{red}{l} \color{red}{=} \color{red}{0}$
    配列vの大きさをNとしたとき
  • $0 \lt r \leq N $

計算量

  • $O(1)$

関連情報

Depends on

Verified with

Code

#include "Hash/zobrist_hash_base.hpp"

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

class ZobristTypeHash : private ZobristHashBase
{
private:
    void build(const vector<long long> &v) override
    {
        hash_vector = vector<unsigned long long>(v.size() + 1, 0);

        set<long long> used;
        for (int i = 0; i < v.size(); i++)
        {
            if (used.contains(v[i]))
            {
                hash_vector[i + 1] = hash_vector[i];
                continue;
            }

            used.insert(v[i]);
            hash_vector[i + 1] = hash_vector[i] ^ ZobristHashBase::hash(v[i]);
        }
    }

public:
    unsigned long long get_range_hash(int l, int r) const override
    {
        assert(l == 0 && l < r && r < hash_vector.size());
        return hash_vector[r];
    }

    ZobristTypeHash(const vector<long long> &v)
    {
        build(v);
    };
};
#line 1 "Hash/zobrist_hash_base.hpp"
#include <bits/stdc++.h>
using namespace std;

class ZobristHashBase
{
private:
    static unsigned long long splitmix64(uint64_t x)
    {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    static unsigned long long generate_random_value(unsigned long long x)
    {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }

protected:
    static unsigned long long hash(long long x)
    {
        static unordered_map<long long, unsigned long long> cache;
        if (cache.contains(x))
        {
            return cache[x];
        }

        cache[x] = generate_random_value(x);
        return cache[x];
    };

    virtual void build(const vector<long long> &v) = 0;
    ZobristHashBase() {};

public:
    vector<unsigned long long> hash_vector;
    virtual unsigned long long get_range_hash(int l, int r) const = 0;
    virtual ~ZobristHashBase() = default;
};
#line 2 "Hash/zobrist_type_hash.hpp"

#line 4 "Hash/zobrist_type_hash.hpp"
using namespace std;

class ZobristTypeHash : private ZobristHashBase
{
private:
    void build(const vector<long long> &v) override
    {
        hash_vector = vector<unsigned long long>(v.size() + 1, 0);

        set<long long> used;
        for (int i = 0; i < v.size(); i++)
        {
            if (used.contains(v[i]))
            {
                hash_vector[i + 1] = hash_vector[i];
                continue;
            }

            used.insert(v[i]);
            hash_vector[i + 1] = hash_vector[i] ^ ZobristHashBase::hash(v[i]);
        }
    }

public:
    unsigned long long get_range_hash(int l, int r) const override
    {
        assert(l == 0 && l < r && r < hash_vector.size());
        return hash_vector[r];
    }

    ZobristTypeHash(const vector<long long> &v)
    {
        build(v);
    };
};
Back to top page