← Back to DSA Course | Chapter 3: Strings | Lesson 6 of 6

Rabin-Karp Algorithm

Hashing Idea

Rabin-Karp searches for a pattern in a text by comparing hash values of the pattern against hash values of every same-length window in the text, rather than comparing characters directly at every position.

Example: Hashing Idea

#include <iostream>
using namespace std;
int hashOf(string s) { int h = 0; for (char c : s) h += c; return h; }
int main() {
    string text = "abcde", pat = "cde";
    int patHash = hashOf(pat);
    int m = pat.size();
    for (int i = 0; i + m <= (int)text.size(); i++) {
        string window = text.substr(i, m);
        cout << "Window \"" << window << "\" hash=" << hashOf(window) << (hashOf(window) == patHash ? " MATCH" : "") << endl;
    }
    return 0;
}
public class Main {
    static int hashOf(String s) { int h = 0; for (char c : s.toCharArray()) h += c; return h; }
    public static void main(String[] args) {
        String text = "abcde", pat = "cde";
        int patHash = hashOf(pat), m = pat.length();
        for (int i = 0; i + m <= text.length(); i++) {
            String window = text.substring(i, i + m);
            System.out.println("Window \"" + window + "\" hash=" + hashOf(window) + (hashOf(window) == patHash ? " MATCH" : ""));
        }
    }
}
def hash_of(s):
    return sum(ord(c) for c in s)

text, pat = "abcde", "cde"
pat_hash, m = hash_of(pat), len(pat)
for i in range(len(text) - m + 1):
    window = text[i:i + m]
    mark = " MATCH" if hash_of(window) == pat_hash else ""
    print(f'Window "{window}" hash={hash_of(window)}{mark}')
#include <stdio.h>
#include <string.h>
int hashOf(char *s, int len) { int h = 0; for (int i = 0; i < len; i++) h += s[i]; return h; }
int main() {
    char text[] = "abcde", pat[] = "cde";
    int m = strlen(pat), patHash = hashOf(pat, m);
    for (int i = 0; i + m <= (int)strlen(text); i++) {
        int h = hashOf(text + i, m);
        printf("Window \"%.*s\" hash=%d%s\n", m, text + i, h, h == patHash ? " MATCH" : "");
    }
    return 0;
}

Rolling Hash

Instead of recomputing a window's hash from scratch as it slides forward, a rolling hash updates the previous window's hash in O(1) by removing the outgoing character's contribution and adding the incoming character's, which is what makes the whole scan fast.

Example: Rolling Hash

#include <iostream>
using namespace std;
int main() {
    string text = "abcde";
    int m = 3;
    int h = 0;
    for (int i = 0; i < m; i++) h += text[i];
    cout << "Window \"" << text.substr(0, m) << "\" hash=" << h << endl;
    h = h - text[0] + text[m];
    cout << "Window \"" << text.substr(1, m) << "\" hash=" << h << " (rolled in O(1))" << endl;
    return 0;
}
public class Main {
    public static void main(String[] args) {
        String text = "abcde";
        int m = 3, h = 0;
        for (int i = 0; i < m; i++) h += text.charAt(i);
        System.out.println("Window \"" + text.substring(0, m) + "\" hash=" + h);
        h = h - text.charAt(0) + text.charAt(m);
        System.out.println("Window \"" + text.substring(1, 1 + m) + "\" hash=" + h + " (rolled in O(1))");
    }
}
text = "abcde"
m = 3
h = sum(ord(c) for c in text[:m])
print(f'Window "{text[:m]}" hash={h}')
h = h - ord(text[0]) + ord(text[m])
print(f'Window "{text[1:1+m]}" hash={h} (rolled in O(1))')
#include <stdio.h>
int main() {
    char text[] = "abcde";
    int m = 3, h = 0;
    for (int i = 0; i < m; i++) h += text[i];
    printf("Window \"%.*s\" hash=%d\n", m, text, h);
    h = h - text[0] + text[m];
    printf("Window \"%.*s\" hash=%d (rolled in O(1))\n", m, text + 1, h);
    return 0;
}

Pattern Search

A matching hash doesn't guarantee a real match, since different strings can collide to the same hash value, so Rabin-Karp always does a direct character-by-character comparison to confirm before reporting a match.

Example: Pattern Search

#include <iostream>
using namespace std;
int main() {
    string text = "abcde", pat = "cde";
    int m = pat.size();
    for (int i = 0; i + m <= (int)text.size(); i++) {
        string window = text.substr(i, m);
        if (window == pat) { cout << "Hash matched at " << i << ", confirmed by direct compare" << endl; }
    }
    return 0;
}
public class Main {
    public static void main(String[] args) {
        String text = "abcde", pat = "cde";
        int m = pat.length();
        for (int i = 0; i + m <= text.length(); i++) {
            if (text.substring(i, i + m).equals(pat)) System.out.println("Hash matched at " + i + ", confirmed by direct compare");
        }
    }
}
text, pat = "abcde", "cde"
m = len(pat)
for i in range(len(text) - m + 1):
    if text[i:i + m] == pat:
        print(f"Hash matched at {i}, confirmed by direct compare")
#include <stdio.h>
#include <string.h>
int main() {
    char text[] = "abcde", pat[] = "cde";
    int m = strlen(pat);
    for (int i = 0; i + m <= (int)strlen(text); i++) {
        if (strncmp(text + i, pat, m) == 0) printf("Hash matched at %d, confirmed by direct compare\n", i);
    }
    return 0;
}

Time Complexity

On average, Rabin-Karp runs close to O(n + m), but a poor hash function that causes frequent collisions forces extra character comparisons, which can degrade its worst case toward O(n × m), same as the naive approach.

Example: Time Complexity

#include <iostream>
using namespace std;
int main() {
    int n = 1000, m = 5;
    cout << "Average case: O(n+m) = " << n + m << endl;
    cout << "Worst case with many collisions: O(n*m) = " << n * m << endl;
    return 0;
}
public class Main {
    public static void main(String[] args) {
        int n = 1000, m = 5;
        System.out.println("Average case: O(n+m) = " + (n + m));
        System.out.println("Worst case with many collisions: O(n*m) = " + (n * m));
    }
}
n, m = 1000, 5
print("Average case: O(n+m) =", n + m)
print("Worst case with many collisions: O(n*m) =", n * m)
#include <stdio.h>
int main() {
    int n = 1000, m = 5;
    printf("Average case: O(n+m) = %d\n", n + m);
    printf("Worst case with many collisions: O(n*m) = %d\n", n * m);
    return 0;
}

Rabin-Karp Practice

Rabin-Karp is especially useful when searching for multiple patterns of the same length at once, since you can hash all the patterns up front and check each text window's hash against that whole set in O(1) per window.

Example: Rabin-Karp Practice

#include <iostream>
#include <set>
using namespace std;
int hashOf(string s) { int h = 0; for (char c : s) h += c; return h; }
int main() {
    set<int> patternHashes = {hashOf("cde"), hashOf("bcd")};
    string text = "abcde";
    int m = 3;
    for (int i = 0; i + m <= (int)text.size(); i++) {
        string window = text.substr(i, m);
        if (patternHashes.count(hashOf(window))) cout << "Window \"" << window << "\" matches a pattern" << endl;
    }
    return 0;
}
import java.util.HashSet;
public class Main {
    static int hashOf(String s) { int h = 0; for (char c : s.toCharArray()) h += c; return h; }
    public static void main(String[] args) {
        HashSet<Integer> patternHashes = new HashSet<>();
        patternHashes.add(hashOf("cde")); patternHashes.add(hashOf("bcd"));
        String text = "abcde";
        int m = 3;
        for (int i = 0; i + m <= text.length(); i++) {
            String window = text.substring(i, i + m);
            if (patternHashes.contains(hashOf(window))) System.out.println("Window \"" + window + "\" matches a pattern");
        }
    }
}
def hash_of(s):
    return sum(ord(c) for c in s)

pattern_hashes = {hash_of("cde"), hash_of("bcd")}
text, m = "abcde", 3
for i in range(len(text) - m + 1):
    window = text[i:i + m]
    if hash_of(window) in pattern_hashes:
        print(f'Window "{window}" matches a pattern')
#include <stdio.h>
#include <string.h>
int hashOf(char *s, int len) { int h = 0; for (int i = 0; i < len; i++) h += s[i]; return h; }
int main() {
    int patternHashes[2];
    patternHashes[0] = hashOf("cde", 3);
    patternHashes[1] = hashOf("bcd", 3);
    char text[] = "abcde";
    int m = 3;
    for (int i = 0; i + m <= (int)strlen(text); i++) {
        int h = hashOf(text + i, m);
        if (h == patternHashes[0] || h == patternHashes[1]) printf("Window \"%.*s\" matches a pattern\n", m, text + i);
    }
    return 0;
}
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.