-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathRabinKarp.cpp
45 lines (40 loc) · 1.42 KB
/
RabinKarp.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
#include "RabinKarp.h"
#include <random>
long long RabinKarp::hash(std::string_view key, int M) const {
long long h = 0;
for (int j = 0; j < M; ++j) h = (R * h + key[j]) % Q;
return h;
}
// a random 31-bit prime
long long RabinKarp::longRandomPrime() {
std::default_random_engine e(std::random_device{}());
std::uniform_int_distribution u(1LL << 30, (1LL << 31) - 1);
while (true) {
long long num = u(e);
if (num % 3 == 0) continue;
bool isPrime = true;
for (long i = 5; i <= num / i; i += 6) {
if (num % i == 0 || num % (i + 2) == 0) {
isPrime = false;
break;
}
}
if (isPrime) return num;
}
}
RabinKarp::RabinKarp(std::string_view pat) : M(pat.length()) {
for (int i = 1; i <= M - 1; ++i) RM = (R * RM) % Q; // Compute R^(M-1) % Q for use in removing leading digit.
patHash = hash(pat, M);
}
int RabinKarp::search(std::string_view txt) const {
int N = txt.length();
long long txtHash = hash(txt, M);
if (patHash == txtHash && check(0)) return 0; // Match at beginning.
// Remove leading digit, add trailing digit, check for match.
for (int i = M; i < N; ++i) {
txtHash = (txtHash + Q - RM * txt[i - M] % Q) % Q;
txtHash = (txtHash * R + txt[i]) % Q;
if (patHash == txtHash && check(i - M + 1)) return i - M + 1; // match
}
return N; // no match found
}