Bird
Raised Fist0
DSA Cprogramming~15 mins

KMP Pattern Matching Algorithm in DSA C - Deep Dive

Choose your learning style10 modes available
Overview - KMP Pattern Matching Algorithm
What is it?
The KMP Pattern Matching Algorithm is a method to find a smaller string (pattern) inside a bigger string (text) efficiently. It avoids checking characters again by remembering where to continue after a mismatch. This makes searching faster than checking every position one by one. It is widely used in text editors, search engines, and DNA sequence analysis.
Why it matters
Without KMP, searching for patterns in text would be slow, especially for large texts or repeated searches. This would make software like search tools or spell checkers less responsive. KMP solves this by reducing unnecessary work, saving time and computing power, which improves user experience and system performance.
Where it fits
Before learning KMP, you should understand basic string handling and simple pattern searching methods like the naive approach. After KMP, you can explore more advanced algorithms like Rabin-Karp or Boyer-Moore for pattern matching, and then move on to string data structures like suffix trees and automata.
Mental Model
Core Idea
KMP remembers how far it matched before a mismatch to skip unnecessary rechecks and continue searching efficiently.
Think of it like...
Imagine reading a book to find a sentence. If you find a mismatch, instead of starting over from the next letter, you remember how much of the sentence matched and jump back to the right spot to continue reading without repeating everything.
Text:    a b c d a b c d a b e
Pattern:       a b c d a b e

Matching steps:
  a b c d a b e
  ↑ ↑ ↑ ↑ ↑ ↑ ↑
If mismatch at last character, jump pattern index back using prefix info instead of starting over.
Build-Up - 7 Steps
1
FoundationUnderstanding Basic Pattern Search
🤔
Concept: Learn how simple pattern search works by checking each position in the text.
The naive method checks the pattern at every position in the text. For each position, it compares characters one by one until a mismatch or full match is found. This can be slow because it repeats comparisons unnecessarily.
Result
If the pattern is 'abc' and text is 'abcabc', naive search checks positions 0,1,2,3 and finds matches at 0 and 3.
Understanding the naive approach shows why repeated checks waste time and sets the stage for improving search efficiency.
2
FoundationConcept of Prefixes and Suffixes
🤔
Concept: Introduce prefixes and suffixes to understand repeated parts inside the pattern.
A prefix is the start part of a string, and a suffix is the end part. For example, in 'abab', 'ab' is both a prefix and suffix. Recognizing these helps us know how the pattern repeats inside itself.
Result
For pattern 'abab', prefixes: '', 'a', 'ab', 'aba', 'abab'; suffixes: '', 'b', 'ab', 'bab', 'abab'. The longest prefix which is also suffix is 'ab'.
Knowing prefix-suffix relations helps us avoid rechecking characters by reusing previous match information.
3
IntermediateBuilding the Longest Prefix Suffix (LPS) Array
🤔Before reading on: do you think the LPS array stores the length of the longest prefix that is also a suffix for each pattern position, or something else? Commit to your answer.
Concept: Create an array that stores, for each position in the pattern, the length of the longest prefix which is also a suffix up to that position.
The LPS array helps us know where to jump in the pattern after a mismatch. We build it by comparing characters in the pattern with previous prefix matches, updating lengths accordingly.
Result
For pattern 'ababaca', LPS array is [0,0,1,2,3,0,1].
Understanding the LPS array is key because it encodes the pattern's internal structure, enabling efficient jumps during search.
4
IntermediateUsing LPS to Skip Comparisons
🤔Before reading on: when a mismatch happens, do you think we restart matching from the next text character or jump inside the pattern using LPS? Commit to your answer.
Concept: Use the LPS array to decide how far to move the pattern index after a mismatch without moving the text index back.
When a mismatch occurs, instead of moving the text pointer back, we use the LPS value to shift the pattern pointer to the longest prefix that matches a suffix, continuing the search efficiently.
Result
This reduces the number of comparisons, making the search run in linear time relative to text length.
Knowing how to use LPS to skip comparisons prevents redundant checks and speeds up pattern matching.
5
IntermediateImplementing KMP Search Algorithm
🤔Before reading on: do you think KMP requires extra memory for LPS and two pointers for text and pattern, or just one pointer? Commit to your answer.
Concept: Combine LPS array and two pointers to implement the full KMP search that finds all pattern occurrences in text efficiently.
We iterate over the text with one pointer and the pattern with another. On match, both move forward. On mismatch, pattern pointer moves using LPS, text pointer stays or moves forward accordingly.
Result
For text 'ababcabcabababd' and pattern 'ababd', KMP finds a match starting at index 10.
Implementing KMP shows how theory translates into practice, achieving fast and reliable pattern search.
6
AdvancedAnalyzing KMP Time Complexity
🤔Before reading on: do you think KMP runs in linear time O(n) or quadratic time O(n*m) where n is text length and m is pattern length? Commit to your answer.
Concept: Understand why KMP runs in linear time by analyzing how pointers move and how LPS prevents rechecking characters.
Each character in text and pattern is visited at most twice. The LPS array ensures that the pattern pointer never moves backward more than necessary, leading to O(n) time complexity.
Result
KMP runs in O(n + m) time, where n is text length and m is pattern length.
Knowing KMP's linear time complexity explains why it outperforms naive search on large inputs.
7
ExpertKMP in Real-World Systems and Limitations
🤔Before reading on: do you think KMP is always the best choice for pattern matching in all scenarios? Commit to your answer.
Concept: Explore how KMP is used in practice, its limitations, and when other algorithms might be better.
KMP is great for exact pattern matching with known patterns. However, for multiple patterns or approximate matches, other algorithms like Aho-Corasick or fuzzy matching are preferred. Also, KMP requires preprocessing which might be costly for very short patterns.
Result
KMP is widely used in text editors and DNA analysis but not always optimal for all pattern matching problems.
Understanding KMP's practical use and limits helps choose the right tool for different pattern matching tasks.
Under the Hood
KMP works by precomputing the LPS array that encodes the longest proper prefix which is also suffix for each pattern prefix. During search, when a mismatch occurs, the algorithm uses the LPS array to shift the pattern pointer to the right position without moving the text pointer backward. This avoids re-examining characters that are known to match, ensuring each character is processed at most twice.
Why designed this way?
KMP was designed to improve on naive search's inefficiency by eliminating redundant comparisons. Early string matching algorithms restarted from the next text character after mismatch, causing repeated work. KMP's insight was to reuse information about the pattern's internal structure to jump intelligently, balancing preprocessing cost with faster search.
Text:  a b a b c a b a b a b a b d
         ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
Pattern:a b a b d
         ↑ ↑ ↑ ↑ ↑

Mismatch at last character 'd' vs 'c'
Use LPS to shift pattern pointer from index 4 to 2
Continue matching without moving text pointer back

LPS array for pattern 'a b a b d': [0,0,1,2,0]
Myth Busters - 4 Common Misconceptions
Quick: does KMP check every character in the text multiple times? Commit yes or no.
Common Belief:KMP checks every character in the text multiple times because it moves pointers back and forth.
Tap to reveal reality
Reality:KMP processes each character in the text at most twice, never moving the text pointer backward, ensuring linear time complexity.
Why it matters:Believing KMP is slow can discourage its use, missing out on its efficiency benefits.
Quick: is the LPS array the same as the pattern itself? Commit yes or no.
Common Belief:The LPS array is just a copy or rearrangement of the pattern characters.
Tap to reveal reality
Reality:The LPS array stores lengths of longest proper prefix-suffix matches, not characters themselves.
Why it matters:Misunderstanding LPS leads to incorrect implementation and failed pattern matching.
Quick: does KMP work for approximate or fuzzy matching? Commit yes or no.
Common Belief:KMP can find patterns even if some characters differ (approximate matching).
Tap to reveal reality
Reality:KMP only works for exact pattern matching; it cannot handle mismatches or errors in the pattern.
Why it matters:Using KMP for approximate matching causes incorrect results and wasted effort.
Quick: is KMP always the fastest pattern matching algorithm? Commit yes or no.
Common Belief:KMP is always the fastest algorithm for any pattern matching problem.
Tap to reveal reality
Reality:KMP is efficient for single exact pattern searches but not always fastest for multiple patterns or very large alphabets.
Why it matters:Choosing KMP blindly can lead to suboptimal performance in complex real-world applications.
Expert Zone
1
The LPS array can be computed in O(m) time without extra space by reusing indices cleverly, which is often overlooked.
2
KMP's efficiency depends on the pattern's structure; highly repetitive patterns lead to longer LPS values and fewer jumps.
3
In some implementations, KMP can be adapted to work with streaming data by maintaining state between chunks.
When NOT to use
Avoid KMP when searching for multiple patterns simultaneously; use Aho-Corasick instead. For approximate or fuzzy matching, use algorithms like Levenshtein distance or Bitap. For very large alphabets or long patterns, Boyer-Moore may be more efficient.
Production Patterns
KMP is used in text editors for find/replace features, in bioinformatics for DNA sequence search, and in network security for pattern detection in data streams. It is often combined with other algorithms for preprocessing or filtering.
Connections
Finite Automata
KMP's LPS array corresponds to states in a finite automaton that processes the pattern.
Understanding KMP as a finite automaton helps grasp how pattern matching can be modeled as state transitions.
Dynamic Programming
Building the LPS array uses overlapping subproblems similar to dynamic programming techniques.
Recognizing this connection clarifies how KMP efficiently reuses previous computations.
Human Learning and Memory
KMP's reuse of previous match information is like how humans remember partial progress to avoid repeating mistakes.
This cross-domain link shows how efficient problem solving often involves remembering and reusing past knowledge.
Common Pitfalls
#1Incorrectly resetting the pattern index to zero after mismatch.
Wrong approach:if (mismatch) patternIndex = 0;
Correct approach:if (mismatch) patternIndex = lps[patternIndex - 1];
Root cause:Misunderstanding that the LPS array tells where to resume instead of restarting from the beginning.
#2Building LPS array by comparing pattern characters with text characters.
Wrong approach:for (i=1; i
Correct approach:for (i=1; i
Root cause:Confusing pattern preprocessing with searching phase.
#3Moving text pointer backward on mismatch.
Wrong approach:if (mismatch) textIndex--;
Correct approach:if (mismatch) patternIndex = lps[patternIndex - 1]; // textIndex stays or moves forward
Root cause:Not realizing KMP never moves text pointer backward, which ensures linear time.
Key Takeaways
KMP algorithm speeds up pattern search by remembering how much of the pattern matched before a mismatch.
The LPS array encodes the longest prefix which is also a suffix for each pattern prefix, enabling efficient jumps.
KMP runs in linear time by never rechecking characters in the text more than twice.
It is designed for exact pattern matching and is not suitable for approximate or multiple pattern searches.
Understanding KMP's internal mechanism helps choose the right algorithm for different text search problems.

Practice

(1/5)
1. What is the main purpose of the KMP (Knuth-Morris-Pratt) algorithm in pattern matching?
easy
A. To efficiently find occurrences of a pattern in a text without rechecking characters
B. To sort the characters of the pattern alphabetically
C. To reverse the text before searching
D. To count the total number of characters in the text

Solution

  1. Step 1: Understand KMP's goal

    KMP algorithm is designed to find all occurrences of a pattern in a text efficiently.
  2. Step 2: Identify how KMP works

    It avoids rechecking characters by using a prefix table to skip unnecessary comparisons.
  3. Final Answer:

    To efficiently find occurrences of a pattern in a text without rechecking characters -> Option A
  4. Quick Check:

    KMP = Efficient pattern search [OK]
Hint: KMP skips repeated checks using prefix info [OK]
Common Mistakes:
  • Thinking KMP sorts or reverses strings
  • Confusing KMP with simple substring search
  • Assuming KMP counts characters only
2. Which of the following correctly declares the prefix (lps) array in C for KMP algorithm of size m?
easy
A. int *lps = malloc(m * sizeof(int));
B. int lps = new int[m];
C. int lps[m];
D. int lps[] = {m};

Solution

  1. Step 1: Understand array declaration in C

    Static arrays like int lps[m]; require constant size or C99 support; dynamic allocation uses malloc.
  2. Step 2: Identify correct dynamic allocation

    int *lps = malloc(m * sizeof(int)); correctly allocates memory for m integers dynamically.
  3. Final Answer:

    int *lps = malloc(m * sizeof(int)); -> Option A
  4. Quick Check:

    Dynamic array = malloc usage [OK]
Hint: Use malloc for dynamic arrays in C [OK]
Common Mistakes:
  • Using Java-style array allocation in C
  • Incorrect static array size syntax
  • Misusing array initialization syntax
3. What will be the output of the following C code snippet using KMP prefix array computation for pattern "ABABC"?
int main() {
    char pattern[] = "ABABC";
    int m = 5, i = 1, len = 0;
    int lps[5] = {0};
    while (i < m) {
        if (pattern[i] == pattern[len]) {
            len++;
            lps[i] = len;
            i++;
        } else {
            if (len != 0) {
                len = lps[len - 1];
            } else {
                lps[i] = 0;
                i++;
            }
        }
    }
    for (int j = 0; j < m; j++) {
        printf("%d ", lps[j]);
    }
    return 0;
}
medium
A. 0 0 1 2 1
B. 0 1 0 1 2
C. 0 1 2 3 4
D. 0 0 1 2 0

Solution

  1. Step 1: Compute lps array step-by-step for "ABABC"

    Index 0: 0; i=1: 'B' != 'A' (len=0) -> lps[1]=0, i=2; i=2: 'A' == 'A' -> len=1, lps[2]=1, i=3; i=3: 'B' == 'B' -> len=2, lps[3]=2, i=4; i=4: 'C' != 'A' (len=2) -> len=lps[1]=0, 'C' != 'A' -> lps[4]=0.
  2. Step 2: Final lps array values

    The lps array is [0, 0, 1, 2, 0]. Output: 0 0 1 2 0
  3. Final Answer:

    0 0 1 2 0 -> Option D
  4. Quick Check:

    lps for "ABABC" = 0 0 1 2 0 [OK]
Hint: Trace lps step-by-step for each pattern char [OK]
Common Mistakes:
  • Miscomputing fallback index in lps
  • Confusing pattern characters during comparison
  • Assuming lps always increases
4. Identify the bug in this KMP prefix array computation snippet and select the fix:
int i = 1, len = 0;
while (i <= m) {
    if (pattern[i] == pattern[len]) {
        len++;
        lps[i] = len;
        i++;
    } else {
        if (len != 0) {
            len = lps[len - 1];
        } else {
            lps[i] = 0;
            i++;
        }
    }
}
medium
A. Remove i++ inside else block
B. Initialize len to 1 instead of 0
C. Change loop condition to i < m
D. Use pattern[len+1] instead of pattern[len]

Solution

  1. Step 1: Analyze loop boundary

    The loop runs while i <= m, but array indices go from 0 to m-1, so i == m causes out-of-bounds access.
  2. Step 2: Correct loop condition

    Changing condition to i < m prevents accessing beyond array size.
  3. Final Answer:

    Change loop condition to i < m -> Option C
  4. Quick Check:

    Loop index must be less than array size [OK]
Hint: Loop till less than array size, not equal [OK]
Common Mistakes:
  • Using <= instead of < causing overflow
  • Incorrect initialization of len
  • Misplacing increment statements
5. Given text "ABABDABACDABABCABAB" and pattern "ABABCABAB", how many times does the KMP algorithm find the pattern in the text?
hard
A. 1
B. 2
C. 3
D. 0

Solution

  1. Step 1: Understand pattern occurrences

    Check the text for exact matches of pattern "ABABCABAB" (length 9).
  2. Step 2: Locate matches in text

    Pattern matches fully at index 10 ("ABABCABAB" from positions 10-18) and also at index 0 ("ABABDABAC" partial mismatch at 4th char but KMP finds overlapping matches). Actually, KMP finds the pattern twice: once starting at index 0 (partial mismatch but KMP continues) and once at index 10 fully matching. The correct count is 2.
  3. Final Answer:

    2 -> Option B
  4. Quick Check:

    Pattern found twice in text [OK]
Hint: Count full pattern matches in text using KMP [OK]
Common Mistakes:
  • Counting partial matches as full
  • Misidentifying additional matches (e.g., at index 14)
  • Overlooking text length boundaries
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard