-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathString-Hashing.cpp
94 lines (84 loc) · 2.32 KB
/
String-Hashing.cpp
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
82
83
84
85
86
87
88
89
90
91
92
93
94
#include<bits/stdc++.h>
using namespace std;
// long long mod0 = 1000000007, mod1 = 987654347;
// long long p0 = 31, p1 = 37;
long long mod0 = 127657753, mod1 = 987654319;
long long p0 = 137, p1 = 277;
vector<array<long long, 2>> pw;
vector<array<long long, 2>> ipw;
long long h(char c) {
return c; // return c - 'a' + 1;
}
long long binpow(long long a, long long b, long long m) {
a %= m;
long long res = 1;
while(b > 0) {
if(b & 1) res = (res * a) % m;
a = (a * a) % m;
b >>= 1;
}
return res;
}
long long inv(long long a, long long m) {
// a is prime and a mod m != 0
// a ^ m === a (mod m)
// a ^ (m - 2) === a ^ -1 (mod m)
return binpow(a, m - 2, m);
}
// Till the limit i.e. [0, limit]
void init(int limit) {
if(pw.empty()) pw.push_back({1, 1});
while((int)pw.size() < limit + 1) {
pw.push_back({
(pw.back()[0] * p0) % mod0,
(pw.back()[1] * p1) % mod1
});
}
if(ipw.empty()) {
ipw.push_back({1, 1});
ipw.push_back({
inv(p0, mod0),
inv(p1, mod1)
});
}
while((int)ipw.size() < limit + 1) {
ipw.push_back({
(ipw.back()[0] * ipw[1][0]) % mod0,
(ipw.back()[1] * ipw[1][1]) % mod1
});
}
}
class Hashing {
public:
vector<array<long long, 2>> pre;
int n;
Hashing(string s) {
init((int)s.size() + 1);
if(s.size() == 0) return;
pre.push_back({(h(s[0]) * pw[0][0]) % mod0, (h(s[0]) * pw[0][1]) % mod1});
for(int i = 1; i < (int)s.size(); i++) {
pre.push_back({
(pre[i - 1][0] + h(s[i]) * pw[i][0]) % mod0,
(pre[i - 1][1] + h(s[i]) * pw[i][1]) % mod1
});
}
n = (int)s.size();
}
array<long long, 2> get_hash(int l, int r) {
assert(0 <= l and l <= r and r < n);
array<long long, 2> hs;
hs[0] = pre[r][0] - (l - 1 >= 0? pre[l - 1][0]: 0) + mod0;
hs[1] = pre[r][1] - (l - 1 >= 0? pre[l - 1][1]: 0) + mod1;
hs[0] = (hs[0] * ipw[l][0]) % mod0;
hs[1] = (hs[1] * ipw[l][1]) % mod1;
return hs;
}
array<long long, 2> get_hash() {
return get_hash(0, n - 1);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
return 0;
}