Find a pattern inside larger text efficiently using direct comparison, prefix preprocessing, rolling hashes and right-to-left character skipping.
LEARNING GOALS
🎯 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.
FOUNDATION
🧭 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.
WHY IT MATTERS
🌍 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.
SEARCH MODEL
📘 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.
DIRECT COMPARISON
🔍 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)
PREFIX PREPROCESSING
🧩 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.
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.
RIGHT-TO-LEFT SKIPPING
⏩ 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.