Finding a pattern Pof lengthMwithin a textTof lengthNis a fundamental problem. While the naive approach takesO(N \cdot M), optimized algorithms achieve linear or sub-linear performance by exploiting the internal structure of the pattern.
KMP avoids re-scanning characters by pre-processing the pattern to find the Longest Proper Prefix which is also a Suffix (LPS).
For every positioniinP,LPS[i]stores the length of the longest proper prefix ofP[0 \dots i]that is also a suffix ofP[0 \dots i].
Example:P = \text{"ABABC"}* A: 0
AB: 0ABA: 1 (A matches A)ABAB: 2 (AB matches AB)ABABC: 0When a mismatch occurs atP[j]andT[i], we do not reseti. Instead, we use the LPS array to "shift" the pattern:j = LPS[j-1]. This ensures we never back-track the text pointer, guaranteeing O(N+M) time complexity.
Boyer-Moore is often faster than KMP in practice because it frequently skips large sections of the text. It scans the pattern from right to left.
When a mismatch occurs atT[i] = c:
If a suffix of the pattern has already matched before the mismatch, we shift the pattern to align that matched suffix with its next occurrence in the pattern.
Rabin-Karp uses a Rolling Hash to find potential matches.
Best For: Multiple pattern matching or searching in data streams.
| Algorithm | Complexity (Avg) | Scan Direction | Key Mechanic |
|---|---|---|---|
| KMP | O(N+M) | Left-to-Right | LPS Array (Prefix/Suffix) |
| Boyer-Moore | O(N/M) | Right-to-Left | Bad Character / Good Suffix |
| Rabin-Karp | O(N+M) | Left-to-Right | Rolling Hash |