Skip to content
DSA in JavaScript
Advanced Strings & DP

Knuth–Morris–Pratt Algorithm

Algorithm · Stretch

Level: StretchString Matching

Step through it: String Matching pattern

text
a
b
a
b
c
a
b
pattern
a
b
c

Step 1 of 5

Goal: find "abc" inside "ababcab". Slide the pattern along the text and compare letter by letter.

Complexity

Time Complexity

  • Time: O(|W| + |T|) (much faster comparing to trivial O(|W| * |T|))

Space Complexity

  • Space: O(|W|)

The Knuth–Morris–Pratt string searching algorithm (or KMP algorithm) searches for occurrences of a "word" W within a main "text string" T by employing the observation that when a mismatch occurs, the word itself embodies sufficient information to determine where the next match could begin, thus bypassing re-examination of previously matched characters.

Code

knuthMorrisPratt.js
/**
 * @see https://www.youtube.com/watch?v=GTJr8OvyEVQ
 * @param {string} word
 * @return {number[]}
 */
function buildPatternTable(word) {
  const patternTable = [0];
  let prefixIndex = 0;
  let suffixIndex = 1;

  while (suffixIndex < word.length) {
    if (word[prefixIndex] === word[suffixIndex]) {
      patternTable[suffixIndex] = prefixIndex + 1;
      suffixIndex += 1;
      prefixIndex += 1;
    } else if (prefixIndex === 0) {
      patternTable[suffixIndex] = 0;
      suffixIndex += 1;
    } else {
      prefixIndex = patternTable[prefixIndex - 1];
    }
  }

  return patternTable;
}

/**
 * @param {string} text
 * @param {string} word
 * @return {number}
 */
export default function knuthMorrisPratt(text, word) {
  if (word.length === 0) {
    return 0;
  }

  let textIndex = 0;
  let wordIndex = 0;

  const patternTable = buildPatternTable(word);

  while (textIndex < text.length) {
    if (text[textIndex] === word[wordIndex]) {
      // We've found a match.
      if (wordIndex === word.length - 1) {
        return (textIndex - word.length) + 1;
      }
      wordIndex += 1;
      textIndex += 1;
    } else if (wordIndex > 0) {
      wordIndex = patternTable[wordIndex - 1];
    } else {
      // wordIndex = 0;
      textIndex += 1;
    }
  }

  return -1;
}

References

Practice

Spotted a mistake or something unclear? Report it on GitHub.

On this page