Skip to content

Commit 525b1ba

Browse files
committed
Implementing KnuthMorrisPratt algorithm
1 parent ef681e8 commit 525b1ba

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.thealgorithms.strings;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* Knuth-Morris-Pratt (KMP) algorithm for substring search.
8+
* This algorithm searches for occurrences of a "pattern" within a main "text" string
9+
* by employing the observation that when a mismatch occurs, the pattern itself
10+
* embodies sufficient information to determine where the next match could begin,
11+
* thus bypassing re-examination of previously matched characters.
12+
* <p>
13+
* Time Complexity: O(n + m), where n is the length of the text and m is the length of the pattern.
14+
* Space Complexity: O(m) for the longest prefix-suffix (LPS) array.
15+
* <p>
16+
* Wikipedia: https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
17+
*
18+
* @author Milad Sadeghi
19+
*/
20+
public final class KnuthMorrisPratt {
21+
22+
// Private constructor to prevent instantiation
23+
private KnuthMorrisPratt() {
24+
}
25+
26+
/**
27+
* Searches for occurrences of a pattern within a text using the Knuth-Morris-Pratt algorithm.
28+
*
29+
* @param text the text to search within
30+
* @param pattern the pattern to search for
31+
* @return a list of starting indices where the pattern is found in the text
32+
*/
33+
public static List<Integer> search(String text, String pattern) {
34+
int n = text.length();
35+
int m = pattern.length();
36+
int[] lps = computeLPSArray(pattern);
37+
int i = 0; // index for sample
38+
int j = 0; // index for pattern
39+
List<Integer> result = new ArrayList<>();
40+
41+
while (i < n) {
42+
if (pattern.charAt(j) == text.charAt(i)) {
43+
i++;
44+
j++;
45+
}
46+
if (j == m) {
47+
System.out.println("Found pattern at index " + (i - j));
48+
result.add(i - j);
49+
j = lps[j - 1];
50+
} else if (i < n && pattern.charAt(j) != text.charAt(i)) {
51+
if (j != 0) {
52+
j = lps[j - 1];
53+
} else {
54+
i++;
55+
}
56+
}
57+
}
58+
return result;
59+
}
60+
61+
/**
62+
* Preprocesses the pattern to create the longest prefix-suffix (LPS) array.
63+
*
64+
* @param pattern the pattern to preprocess
65+
* @return the LPS array
66+
*/
67+
private static int[] computeLPSArray(String pattern) {
68+
int m = pattern.length();
69+
int[] lps = new int[m];
70+
int j = 0;
71+
int i = 1;
72+
while (i < m) {
73+
if (pattern.charAt(i) == pattern.charAt(j)) {
74+
j++;
75+
lps[i] = j;
76+
i++;
77+
} else {
78+
if (j != 0) {
79+
j = lps[j - 1];
80+
} else {
81+
lps[i] = 0;
82+
i++;
83+
}
84+
}
85+
}
86+
return lps;
87+
}
88+
}

0 commit comments

Comments
 (0)