CODEBHAVYA • ADS LEVEL 11

🔤 String Pattern Matching

Find a pattern inside larger text efficiently using direct comparison, prefix preprocessing, rolling hashes and right-to-left character skipping.

🎯 Learning Objectives

After completing this level, you should be able to:

  • Explain text, pattern, alignment, shift and occurrence.
  • Implement the Naive and KMP pattern-matching algorithms.
  • Construct and interpret the KMP LPS array.
  • Explain rolling hashes and hash collisions in Rabin–Karp.
  • Apply the Boyer–Moore bad-character heuristic.
  • Compare preprocessing, search time and suitable applications.
  • Select an appropriate algorithm for repeated, large or multi-pattern searches.

🧭 1. What Is Pattern Matching?

Given a text T of length n and a pattern P of length m, pattern matching finds every starting index where P occurs in T.

Example: Text = ABABA, Pattern = ABA. Matches begin at indices 0 and 2; overlapping occurrences are valid.

Text

The larger sequence being searched.

T[0 … n−1]

Pattern

The smaller sequence we want to locate.

P[0 … m−1]
Edge cases: Decide how your program handles an empty pattern, a pattern longer than the text, repeated characters, overlaps and case sensitivity.

🌍 2. Applications

🔎

Search Engines

Locate words, phrases and tokens inside indexed documents.

🧬

Bioinformatics

Search DNA and protein sequences for important motifs.

🛡️

Cybersecurity

Detect signatures and suspicious patterns in network traffic.

📝

Editors

Support Find, Replace and syntax-highlighting operations.

🧱

Compilers

Recognize tokens and language constructs during lexical analysis.

📊

Log Analysis

Locate errors, identifiers and event sequences in large logs.

📘 3. Alignment, Shift and Comparison

1

Align

Place P below a candidate window of T.

2

Compare

Test the aligned characters according to the algorithm.

3

Shift

Move P using one position or information already learned.

4

Report

Record the starting index after all m characters match.

Possible alignments: when m ≤ n, the pattern can begin at n − m + 1 positions.

🔍 4. Naive Pattern Matching

The Naive method tries every possible shift and compares pattern characters from left to right.

for (shift = 0; shift <= n - m; shift++) {
    for (j = 0; j < m; j++)
        if (text[shift + j] != pattern[j]) break;
    if (j == m) report(shift);
}

Strength

No preprocessing and very easy to implement.

Space: O(1)

Weakness

It may recheck many characters after each mismatch.

Worst time: O(nm)

🧩 5. Knuth–Morris–Pratt (KMP)

KMP preprocesses the pattern so a mismatch does not force the text pointer to move backward. It uses the LPS array.

LPS[i] is the length of the longest proper prefix of P[0…i] that is also a suffix of that substring. “Proper” means the prefix is not the entire substring.
Pattern index012345678
PatternABABCABAB
LPS001201234
Character match

Advance both i and j.

Mismatch and j > 0

Set j = LPS[j−1]; do not move i.

Mismatch and j = 0

Advance only i.

j reaches m

Report i−j, then continue using LPS[m−1].

KMP complexity: LPS preprocessing O(m) + search O(n) = O(n + m).

#️⃣ 6. Rabin–Karp Algorithm

Rabin–Karp compares a hash of the pattern with the hash of each text window. A rolling hash updates the next window efficiently.

1

Hash Pattern

Calculate the pattern hash once.

2

Hash Window

Calculate the first m-character text hash.

3

Compare Hashes

Different hashes guarantee different strings.

4

Verify

Equal hashes require character comparison because collisions are possible.

Spurious hit: two different strings may have the same hash. Always verify the characters before reporting a match.

Expected search time is O(n + m) with a good hash, while the worst case is O(nm) when many collisions occur.

⏩ 7. Boyer–Moore Method

Boyer–Moore compares the pattern from right to left and can skip several text positions after a mismatch.

Bad-Character Rule

Align the mismatching text character with its last occurrence in the pattern, or move past it if absent.

Uses a last-occurrence table

Good-Suffix Rule

Reuse information about a suffix that already matched before the mismatch.

Allows larger safe shifts
Practical advantage: Boyer–Moore often examines fewer than n text characters for long patterns over large alphabets, although its exact guarantees depend on the implemented heuristics.

⚖️ 8. Comparison of Methods

AlgorithmPreprocessingTypical/Worst SearchMain IdeaUseful When
NaiveNoneO(nm) worstTry every alignmentSmall inputs and simple code
KMPO(m)O(n)LPS prefix fallbackGuaranteed linear single-pattern search
Rabin–KarpO(m)O(n) expected; O(nm) worstRolling hashMany patterns or plagiarism-style scanning
Boyer–MooreAlphabet + patternOften sublinear; variant-dependent worst caseRight-to-left comparisons and skipsLong patterns and large alphabets
INTERACTIVE ALGORITHM VISUALIZATION

🎬 9. Premium Pattern-Matching Visualizer

CodeBhavya

Enter a text and pattern, choose an algorithm and click Load Visualizer. The animation is created only after the button is pressed.

Choose an example or enter values, then click Load Visualizer.

💻 10. KMP Pattern Matching in C

#include <stdio.h>
#include <string.h>

void buildLPS(const char pattern[], int m, int lps[]) {
    int length = 0, i = 1;
    lps[0] = 0;
    while (i < m) {
        if (pattern[i] == pattern[length])
            lps[i++] = ++length;
        else if (length != 0)
            length = lps[length - 1];
        else
            lps[i++] = 0;
    }
}

void kmpSearch(const char text[], const char pattern[]) {
    int n = strlen(text), m = strlen(pattern), lps[m];
    buildLPS(pattern, m, lps);
    int i = 0, j = 0;
    while (i < n) {
        if (text[i] == pattern[j]) { i++; j++; }
        if (j == m) {
            printf("Match at index %d\n", i - j);
            j = lps[j - 1];
        } else if (i < n && text[i] != pattern[j]) {
            if (j != 0) j = lps[j - 1];
            else i++;
        }
    }
}

int main(void) {
    char text[200], pattern[100];
    scanf("%199s %99s", text, pattern);
    kmpSearch(text, pattern);
    return 0;
}

Sample Input

ABABDABACDABABCABAB
ABABCABAB

Sample Output

Match at index 10

🔍 11. Program Tracing — KMP Search

Trace text = ABABAC, pattern = ABAC and LPS = [0, 0, 1, 0]. Every value change is connected to the highlighted statement.

📈 12. Complexity Analysis

AlgorithmBest/ExpectedWorstExtra Space
NaiveO(n)O(nm)O(1)
KMPO(n + m)O(n + m)O(m)
Rabin–KarpO(n + m) expectedO(nm)O(1) or O(k)
Boyer–MooreOften sublinearVariant-dependentO(m + alphabet)

💡 13. Important Questions and Decisions

Why does KMP never move i backward?

The LPS array preserves the longest prefix already known to match, so comparison resumes at a safe pattern position.

Why verify equal hashes?

A hash collision can make different strings share the same hash value.

How are overlaps reported?

After a match, continue from the appropriate prefix value instead of resetting blindly.

Which method for many patterns?

Rabin–Karp can compare several pattern hashes; tries or Aho–Corasick are better for large pattern sets.

⚠️ 14. Common Mistakes

❌ Incorrect LPS meaning

LPS stores a length, not a direct text shift or character index.

❌ Moving both pointers on mismatch

In KMP, i stays fixed when j falls back through LPS.

❌ Reporting a hash as a match

Equal hashes must be verified character by character.

❌ Missing overlaps

Continue with LPS after a full match to discover overlapping occurrences.

✍️ 15. Practice Problems

Solve each question first. Use Hint only when needed and Show Answer to verify your reasoning.

1. How many alignments exist when n = 12 and m = 5?

2. Find all occurrences of ABA in ABABA.

3. Give the worst-case time complexity of Naive matching.

4. What does LPS stand for?

5. Construct the LPS array for AAAA.

6. Construct the LPS array for ABAC.

7. In KMP, what happens on a mismatch when j > 0?

8. In KMP, what happens on a mismatch when j = 0?

9. Why is KMP linear?

10. What is a rolling hash?

11. What is a spurious hit in Rabin–Karp?

12. Why does Rabin–Karp verify characters after equal hashes?

13. From which direction does Boyer–Moore normally compare?

14. What information does the bad-character table store?

15. Which algorithm gives guaranteed O(n + m) search including preprocessing?

16. Which method is simplest for a tiny one-time input?

17. What should KMP do after finding a match if overlaps are required?

18. What is the LPS array for ABCD?

19. If m > n, how many valid pattern alignments exist?

20. Choose a suitable method for searching many patterns by hash inside one document.

📝 16. Quick Revision

  • Pattern matching finds every valid starting index of P in T.
  • Naive matching tries all n−m+1 alignments.
  • KMP uses LPS and never moves the text pointer backward.
  • LPS describes reusable prefix–suffix structure inside the pattern.
  • Rabin–Karp uses rolling hashes but verifies equal-hash windows.
  • Boyer–Moore compares from right to left and makes larger safe shifts.
  • Overlapping matches require continuing from a valid prefix state.
  • Choose the algorithm according to guarantees, alphabet, pattern count and input size.