The Knuth-Morris-Pratt (KMP) algorithm is a string searching algorithm that is used to find occurrences of a pattern within a larger string. The algorithm achieves this by preprocessing the pattern to construct a table of partial matches, which is then used to avoid unnecessary comparisons when searching for the pattern within the larger string.
The KMP algorithm works as follows:
Construct a table of partial matches for the pattern.
The table is an array lps of the same length as the pattern.
The value lps[i] at index i represents the length of the longest proper suffix of the substring pattern[0:i] that is also a prefix of the same substring.
The value of lps[0] is always 0, as a string of length 1 has no proper suffix.
Use the lps table to search for the pattern within the larger string.
Initialize two pointers, i and j, to 0 and 0, respectively.
While i is less than the length of the larger string:
If the character at index i of the larger string matches the character at index j of the pattern, increment both i and j.
If j is equal to the length of the pattern, then a match has been found and the index of the first occurrence of the pattern within the larger string is i - j.
If the character at index i of the larger string does not match the character at index j of the pattern:
If j is equal to 0, increment i.
Otherwise, set j to lps[j-1].
The KMP algorithm is particularly useful when searching for a pattern within a large string, as it can avoid unnecessary comparisons by using the lps table to skip over parts of the larger string that are guaranteed not to match the pattern. This makes the algorithm more efficient than other naive string searching algorithms, such as the brute-force method of comparing each possible substring of the larger string with the pattern.
Here is an example implementation of the KMP algorithm in Java:
public static List<Integer> kmp(String text, String pattern) {
List<Integer> indices = new ArrayList<Integer>();
int n = text.length();
int m = pattern.length();
int[] lps = computeLPS(pattern);
int i = 0, j = 0;
while (i < n) {
if (text.charAt(i) == pattern.charAt(j)) {
i++;
j++;
if (j == m) {
indices.add(i - j);
j = lps[j - 1];
}
} else if (j > 0) {
j = lps[j - 1];
} else {
i++;
}
}
return indices;
}
private static int[] computeLPS(String pattern) {
int m = pattern.length();
int[] lps = new int[m];
int i = 1, j = 0;
while (i < m) {
if (pattern.charAt(i) == pattern.charAt(j)) {
j++;
lps[i] = j;
i++;
} else if (j > 0) {
j = lps[j - 1];
} else {
lps[i] = 0;
i++;
}
}
return lps;
}
In this implementation, the kmp method takes as input a larger string text and a pattern string pattern, and