forked from mapsme/omim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrolling_hash.hpp
81 lines (70 loc) · 1.89 KB
/
rolling_hash.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#pragma once
#include "base/assert.hpp"
#include "base/base.hpp"
#include "base/math.hpp"
#ifdef DEBUG
#include <queue>
#endif
template <typename T, typename HashT> class RabinKarpRollingHasher
{
public:
using value_type = T;
using hash_type = HashT;
explicit RabinKarpRollingHasher(HashT multiplier)
: m_multiplier(multiplier)
{
}
template <typename Iter> hash_type Init(Iter it, uint64_t windowSize)
{
ASSERT_GREATER(m_windowSize, 0, ());
m_windowSize = windowSize;
m_removeMultiplier = base::PowUint(m_multiplier, m_windowSize - 1);
#ifdef DEBUG
while (!m_queue.empty()) m_queue.pop();
#endif
m_hash = 0;
for (uint64_t i = 0; i < m_windowSize; ++it, ++i)
{
m_hash = m_hash * m_multiplier + *it;
#ifdef DEBUG
m_queue.push(*it);
#endif
}
return m_hash;
}
hash_type Scroll(T const remove, T const add)
{
ASSERT_NOT_EQUAL(m_removeMultiplier, 0, (m_multiplier, m_windowSize, remove, add));
ASSERT_NOT_EQUAL(m_windowSize, 0, (m_multiplier, remove, add));
#ifdef DEBUG
ASSERT_EQUAL(m_queue.front(), remove, ());
m_queue.pop();
m_queue.push(add);
#endif
m_hash -= m_removeMultiplier * remove;
m_hash = m_hash * m_multiplier + add;
return m_hash;
}
private:
hash_type m_hash = 0;
hash_type m_multiplier = 1;
hash_type m_removeMultiplier = 1;
uint64_t m_windowSize = 1;
#ifdef DEBUG
std::queue<value_type> m_queue;
#endif
};
class RabinKarpRollingHasher32 : public RabinKarpRollingHasher<uint32_t, uint32_t>
{
public:
RabinKarpRollingHasher32()
: RabinKarpRollingHasher<uint32_t, uint32_t>(1103515245U) {}
};
class RabinKarpRollingHasher64 : public RabinKarpRollingHasher<uint64_t, uint64_t>
{
public:
RabinKarpRollingHasher64()
: RabinKarpRollingHasher<uint64_t, uint64_t>(6364136223846793005ULL) {}
};
using RollingHasher32 = RabinKarpRollingHasher32;
using RollingHasher64 = RabinKarpRollingHasher64;