What if you could find a phrase in a huge book almost instantly without reading every word?
Why Rabin Karp String Matching in DSA Typescript?
Imagine you have a huge book and you want to find every place where a certain phrase appears. You try to read every page and check each word one by one to see if it matches your phrase.
This manual way is very slow and tiring. Checking every word and comparing it letter by letter wastes a lot of time, especially if the book is very long or the phrase appears many times.
Rabin Karp uses a clever trick: it turns words into numbers (called hashes) so it can quickly compare these numbers instead of letters. This way, it can skip many unnecessary checks and find matches faster.
for (let i = 0; i <= text.length - pattern.length; i++) { if (text.substring(i, i + pattern.length) === pattern) { console.log('Match at', i); } }
let patternHash = hash(pattern); for (let i = 0; i <= text.length - pattern.length; i++) { let currentHash = hash(text.substring(i, i + pattern.length)); if (currentHash === patternHash) { console.log('Match at', i); } }
It enables fast searching of patterns in large texts by comparing numbers instead of letters.
Search engines use this method to quickly find your search words inside billions of web pages.
Manual letter-by-letter search is slow for big texts.
Rabin Karp uses hashing to speed up pattern matching.
This method helps find matches quickly and efficiently.
Practice
Rabin Karp String Matching algorithm?Solution
Step 1: Understand the algorithm's approach
The Rabin Karp algorithm uses a hash function to convert strings into numbers for quick comparison.Step 2: Identify the benefit of hashing
Hashing allows checking if substrings match the pattern by comparing hash values instead of characters directly.Final Answer:
Use hashing to find pattern matches efficiently -> Option AQuick Check:
Rabin Karp = hashing for matching [OK]
- Thinking it uses recursion
- Assuming it sorts strings before matching
- Confusing it with brute force checking
s of length m using a base d and a prime modulus q in TypeScript?Solution
Step 1: Understand the rolling hash formula
The hash is computed as hash = (hash * d + current_char) mod q for each character.Step 2: Match the code with the formula
let hash = 0; for(let i=0; iFinal Answer:
let hash = 0; for(let i=0; i -> Option AQuick Check:
Rolling hash = (prev_hash * d + char) % q [OK]
- Mixing up base and modulus in calculation
- Starting hash from 1 instead of 0
- Incorrect order of operations in formula
"abc" in text "ababcabc"?
const text = "ababcabc";
const pattern = "abc";
const d = 256;
const q = 101;
function rabinKarp(text: string, pattern: string): number[] {
const m = pattern.length;
const n = text.length;
let p = 0, t = 0, h = 1;
const result: number[] = [];
for (let i = 0; i < m - 1; i++) h = (h * d) % q;
for (let i = 0; i < m; i++) {
p = (d * p + pattern.charCodeAt(i)) % q;
t = (d * t + text.charCodeAt(i)) % q;
}
for (let i = 0; i <= n - m; i++) {
if (p === t) {
let match = true;
for (let j = 0; j < m; j++) {
if (text[i + j] !== pattern[j]) {
match = false;
break;
}
}
if (match) result.push(i);
}
if (i < n - m) {
t = (d * (t - text.charCodeAt(i) * h) + text.charCodeAt(i + m)) % q;
if (t < 0) t += q;
}
}
return result;
}
console.log(rabinKarp(text, pattern));Solution
Step 1: Identify pattern occurrences in text
The pattern "abc" appears starting at index 2 ("ababcabc") and index 5.Step 2: Verify code logic for matching indices
The code correctly finds these two positions and returns [2, 5].Final Answer:
[2, 5] -> Option DQuick Check:
Pattern found at indices 2 and 5 [OK]
- Including index 0 which is partial match
- Confusing overlapping matches
- Forgetting to adjust negative hash values
function rabinKarpBug(text: string, pattern: string): number[] {
const m = pattern.length;
const n = text.length;
const d = 256;
const q = 101;
let p = 0, t = 0, h = 1;
const result: number[] = [];
for (let i = 0; i < m; i++) h = (h * d) % q;
for (let i = 0; i < m; i++) {
p = (d * p + pattern.charCodeAt(i)) % q;
t = (d * t + text.charCodeAt(i)) % q;
}
for (let i = 0; i <= n - m; i++) {
if (p === t) {
let match = true;
for (let j = 0; j < m; j++) {
if (text[i + j] !== pattern[j]) {
match = false;
break;
}
}
if (match) result.push(i);
}
if (i < n - m) {
t = (d * (t - text.charCodeAt(i) * h) + text.charCodeAt(i + m)) % q;
if (t < 0) t += q;
}
}
return result;
}Solution
Step 1: Check computation of h
Variable h should be (d^(m-1)) % q, but loop runs m times, making h too large.Step 2: Understand impact on rolling hash
Incorrect h causes wrong subtraction in rolling hash, leading to incorrect matches.Final Answer:
The initial value of h is computed incorrectly; it should be for (i = 0; i < m-1; i++) -> Option BQuick Check:
h loop runs m-1 times, not m [OK]
- Calculating h with wrong loop range
- Forgetting modulo in hash updates
- Misindexing pattern or text in loops
"aaa" in text "aaaaaa". What is the output of the algorithm and why is it important to verify matches after hash comparison?Solution
Step 1: Identify all pattern occurrences in text
The pattern "aaa" appears starting at indices 0, 1, 2, and 3 in "aaaaaa" due to overlapping.Step 2: Explain importance of verifying matches after hash
Hash collisions can cause false positives, so character-by-character check confirms actual matches.Final Answer:
[0, 1, 2, 3], because overlapping matches exist and hash collisions can occur -> Option CQuick Check:
Overlapping matches + verify after hash = [0,1,2,3] [OK]
- Ignoring overlapping matches
- Assuming hash guarantees no false positives
- Counting only first or non-overlapping matches
Ready to prove it?
Pass the test and this pattern moves unknown
