Module A-11·16 min read

Rabin-Karp rolling hashes and KMP's failure function — finding a pattern in a text faster than brute force.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module A-11 — String Matching: Rabin-Karp and KMP

What this module covers: Finding a pattern inside a larger text — the job behind every grep, every log search, every "find in file" — has a naive solution that's O(n × m), the same quadratic shape flagged throughout this course. This module covers two different fixes: Rabin-Karp, which compares hashes instead of characters using a rolling hash (Module F-9's sliding window, made multiplicative), and KMP, which never backtracks in the text at all, by precomputing exactly how much progress can be reused after a mismatch.


The Naive Approach's Cost

typescript

For every one of the roughly n starting positions in text, this potentially compares up to m characters (the pattern's length) before finding a mismatch — O(n × m) in the worst case (imagine searching for "aaaaab" inside "aaaaaaaaaaaaaaaa" — nearly every position gets a long, failed near-match before giving up). Both fixes below avoid this by never blindly re-comparing characters that a smarter approach could have ruled out or skipped.


Rabin-Karp: Compare Hashes, Not Characters

The idea: compute a hash of the pattern once, then compute a hash of every same-length window in the text — if two hashes don't match, the strings definitely don't match, skipping a full character-by-character comparison entirely. The trick that makes this fast is a rolling hash: updating the previous window's hash to the next window's hash in O(1), rather than recomputing it from scratch.

typescript

The rolling update is exactly Module F-9's sliding window idea (subtract what's leaving, add what's entering, avoid recomputing from scratch), just multiplicative instead of additive: treating the window as a base-256 number, removing the leftmost character's contribution, shifting everything up one digit, and adding the new rightmost character. This keeps each window's hash update O(1), so the whole scan is O(n) for hashing plus O(m) for the initial pattern hash — O(n + m) on average. The hash comparison is a screening step, not a guarantee — two different strings can occasionally hash to the same value (a collision), which is exactly why the code still does a direct text.slice(i, i + m) === pattern comparison before confirming a match; with enough collisions (a poorly chosen hash, or an adversarial input), this degrades back toward O(n × m) in the worst case, but is O(n + m) in the typical case.


KMP: Never Backtrack in the Text

Knuth-Morris-Pratt takes a different approach entirely: precompute, for every prefix of the pattern, how much of a match can be reused after a mismatch, so the text pointer never has to move backward — only the pattern pointer resets, using information already known from the pattern itself.

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.