-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrabin-karp.cpp
More file actions
91 lines (74 loc) · 2.57 KB
/
rabin-karp.cpp
File metadata and controls
91 lines (74 loc) · 2.57 KB
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
// Rabin-Karp Algorithm for String Matching
// Assumes lowercase English letters only ('a' to 'z')
// Time Complexity: O(n + m) average
// Space Complexity: O(1), excluding result storage
#include <bits/stdc++.h>
using namespace std;
// Use 64-bit integers to safely handle large hash values
using ll = long long;
// Constants
const int BASE = 26; // Alphabet size for lowercase letters
const ll MOD = 1e9 + 7; // Large prime modulus to reduce collisions
vector<int> rabinKarpSearch(const string& text, const string& pattern)
{
int textLength = text.size();
int patternLength = pattern.size();
// Edge case: pattern longer than text
if (patternLength > textLength)
return {};
vector<int> matchingIndices;
ll patternHash = 0; // Hash of the pattern
ll windowHash = 0; // Hash of current window in the text
ll highestPower = 1; // BASE^(patternLength - 1) % MOD
// Precompute highest power of base used in hash rolling
for (int i = 0; i < patternLength - 1; ++i)
{
highestPower = (highestPower * BASE) % MOD;
}
// Compute the hash of the pattern and the first window in text
for (int i = 0; i < patternLength; ++i)
{
patternHash = (patternHash * BASE + (pattern[i] - 'a')) % MOD;
windowHash = (windowHash * BASE + (text[i] - 'a')) % MOD;
}
// Slide the window over the text
for (int i = 0; i <= textLength - patternLength; ++i)
{
// Check hash match
if (patternHash == windowHash)
{
// Confirm actual match to eliminate false positives from hash collisions
bool isMatch = true;
for (int j = 0; j < patternLength; ++j)
{
if (text[i + j] != pattern[j])
{
isMatch = false;
break;
}
}
if (isMatch)
matchingIndices.push_back(i);
}
// Update the rolling hash: remove left char and add right char
if (i < textLength - patternLength)
{
ll leftChar = (text[i] - 'a') * highestPower % MOD;
windowHash = (windowHash - leftChar + MOD) % MOD;
windowHash = (windowHash * BASE + (text[i + patternLength] - 'a')) % MOD;
}
}
return matchingIndices;
}
// Sample usage
int main()
{
string text = "ababcabcababc";
string pattern = "abc";
vector<int> result = rabinKarpSearch(text, pattern);
for (int index : result)
{
cout << "Pattern found at index: " << index << endl;
}
return 0;
}