-
Notifications
You must be signed in to change notification settings - Fork 21.1k
Expand file tree
/
Copy pathKnuthMorrisPratt.java
More file actions
84 lines (79 loc) · 2.5 KB
/
KnuthMorrisPratt.java
File metadata and controls
84 lines (79 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package com.thealgorithms.strings;
import java.util.ArrayList;
import java.util.List;
/**
* Implementation of the Knuth–Morris–Pratt (KMP) string matching algorithm.
* KMP efficiently searches for occurrences of a pattern within a text by
* utilizing a pre-computed failure function to avoid redundant comparisons.
* Time Complexity: O(n + m) where n is text length and m is pattern length.
*/
final class KnuthMorrisPratt {
private KnuthMorrisPratt() {
}
/**
* Compute the Longest Proper Prefix which is also Suffix (LPS) array
* for the given pattern. This array is used to avoid unnecessary
* character comparisons during the search phase.
*
* @param pattern the pattern to compute LPS for
* @return the LPS array
*/
public static int[] computeLps(final String pattern) {
final int n = pattern.length();
final int[] lps = new int[n];
int len = 0;
lps[0] = 0;
int i = 1;
while (i < n) {
if (pattern.charAt(i) == pattern.charAt(len)) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
/**
* Search for all occurrences of the pattern in the text.
* Returns a list of starting indices where the pattern is found.
*
* @param text the text to search in
* @param pattern the pattern to search for
* @return list of starting indices of pattern occurrences
*/
public static List<Integer> search(final String text, final String pattern) {
final List<Integer> occurrences = new ArrayList<>();
if (pattern == null || pattern.isEmpty() || text == null) {
return occurrences;
}
final int[] lps = computeLps(pattern);
int i = 0;
int j = 0;
final int n = text.length();
final int m = pattern.length();
while (i < n) {
if (text.charAt(i) == pattern.charAt(j)) {
i++;
j++;
if (j == m) {
occurrences.add(i - j);
j = lps[j - 1];
}
} else {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return occurrences;
}
}