Learn › Strings & pattern matching

KMP & the failure function

Never re-compare a matched prefix: precompute borders and skip in O(n + m). · 12 min read

The key idea

When the naive scan mismatches after matching a prefix of P, it throws that work away. KMP (Knuth–Morris–Pratt) instead asks: how much of what I just matched is also a prefix of `P`? That overlap (a border) is exactly how far the pattern can safely slide without missing a match — so we never move the text pointer backward.

The failure function (prefix function)

For each position i, π[i] = the length of the longest proper prefix of P[0..i] that is also a suffix of it. It's precomputed in O(m) by matching the pattern against itself:

vector<int> prefix_function(const string& p) {
    int m = p.size();
    vector<int> pi(m, 0);
    for (int i = 1, k = 0; i < m; i++) {
        while (k > 0 && p[i] != p[k]) k = pi[k - 1];
        if (p[i] == p[k]) k++;
        pi[i] = k;
    }
    return pi;
}

Matching with the table

Scan the text once. Keep j = how many pattern characters currently match. On a mismatch, jump j = π[j-1] (slide the pattern using its border) instead of restarting. The text index never goes backward, so it's linear.

Interactive visualization: KMP: skip ahead with the failure function — step through it frame by frame on this page.

KMP is linear
  1. build π in O(m) — Self-match of the pattern.
  2. scan text, i never moves back — Each char advances i or shrinks j.
  3. O(n) for the scan — Amortised over j's increases/decreases.

Result: O(n + m) time, O(m) space

Rolling hash (Rabin–Karp)

Another approach: hash the pattern and every length-m window of the text. A rolling hash updates the window hash in O(1) as it slides (remove the leaving char, add the entering one), giving O(n + m) average time. Verify on a hash hit to avoid false positives. It generalises nicely to 2D and multi-pattern search.

Practice: Longest Happy Prefix (Hard) — Longest proper prefix that is also a suffix — the KMP failure value.

Previous: Pattern matching: the naive scan · Next: Divisibility, GCD & modular arithmetic

More in Strings & pattern matching