Knuth-Morris-Pratt (KMP) pattern searching algorithm explained step-by-step: Longest Prefix Suffix (LPS) table construction, non-backtracking text pointer, complexity proofs, and JavaScript implementation.
The Knuth-Morris-Pratt (KMP) string-searching algorithm searches for all occurrences of a pattern P of length M inside a text T of length N in deterministic O(N + M) linear time.
Naive string matching checks every alignment and backtracks the text pointer on every mismatch, degrading to O(N · M) worst-case time (e.g., searching "AAAAAB" inside "AAAAAAAAAA"). KMP solves this by precomputing the Longest Proper Prefix that is also a Suffix (LPS array) for the pattern. When a mismatch occurs, KMP shifts the pattern to resume matching without ever rewinding the text pointer.
Compute `lps[i]`, the length of the longest proper prefix of `pattern[0...i]` that is also a suffix of `pattern[0...i]`. An LPS value of 3 means the first 3 characters match the last 3 characters of that substring.
Set pointer `i = 0` for the text string and pointer `j = 0` for the pattern string.
If `text[i] === pattern[j]`, increment both `i` and `j`. When `j === pattern.length`, a complete match is found at index `i - j`. Next, set `j = lps[j - 1]` to continue scanning for overlapping occurrences.
If `text[i] !== pattern[j]`, fall back using `j = lps[j - 1]` (if `j > 0`) without changing `i`. If `j === 0`, simply advance `i++`. The text pointer `i` never moves backwards.
1function computeLPSArray(pattern) {2 const lps = new Array(pattern.length).fill(0);3 let len = 0; // Length of previous longest prefix suffix4 let i = 1;5 6 while (i < pattern.length) {7 if (pattern[i] === pattern[len]) {8 len++;9 lps[i] = len;10 i++;11 } else {12 if (len !== 0) {13 len = lps[len - 1]; // Fallback to previous longest prefix14 } else {15 lps[i] = 0;16 i++;17 }18 }19 }20 return lps;21}22 23function kmpSearch(text, pattern) {24 if (!pattern || !text || pattern.length > text.length) return [];25 26 const lps = computeLPSArray(pattern);27 const matches = [];28 let i = 0; // index pointer for text29 let j = 0; // index pointer for pattern30 31 while (i < text.length) {32 if (pattern[j] === text[i]) {33 i++;34 j++;35 }36 37 if (j === pattern.length) {38 matches.push(i - j); // Found match starting at index (i - j)39 j = lps[j - 1]; // Check for overlapping matches40 } else if (i < text.length && pattern[j] !== text[i]) {41 if (j !== 0) {42 j = lps[j - 1]; // Shift pattern using LPS without rewinding i43 } else {44 i++;45 }46 }47 }48 49 return matches;50}51 52// Example usage:53// kmpSearch("ABABDABACDABABCABAB", "ABABCABAB"); // Returns [10]The full interactive roadmap is unlocking — these specialized modules land in upcoming releases.
This feature will be implemented in the next update.
This feature will be implemented in the next update.
This feature will be implemented in the next update.
Explore the full catalog — 30+ algorithms with more unlocking every release.
Test your understanding of Knuth-Morris-Pratt (KMP) Algorithm complexity and step mechanics.
Q1.What is the primary advantage of KMP over naive string searching?
Q2.What does the LPS table value `lps[i] = 3` signify for `pattern[0...i]`?
Apply Knuth-Morris-Pratt (KMP) Algorithm to real coding interview questions.
Given two strings needle and haystack, return the index of the first occurrence of needle in haystack.
Check if a string can be constructed by taking a substring of it and appending multiple copies of the substring together.