Skip to content

Commit 965c203

Browse files
authored
Add KMP String Search Algorithm (#3200)
1 parent 3918d9e commit 965c203

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.thealgorithms.searches;
2+
3+
class KMPSearch {
4+
int KMPSearch(String pat, String txt)
5+
{
6+
int M = pat.length();
7+
int N = txt.length();
8+
9+
// create lps[] that will hold the longest
10+
// prefix suffix values for pattern
11+
int lps[] = new int[M];
12+
int j = 0; // index for pat[]
13+
14+
// Preprocess the pattern (calculate lps[]
15+
// array)
16+
computeLPSArray(pat, M, lps);
17+
18+
int i = 0; // index for txt[]
19+
while ((N - i) >= (M - j)) {
20+
if (pat.charAt(j) == txt.charAt(i)) {
21+
j++;
22+
i++;
23+
}
24+
if (j == M) {
25+
System.out.println("Found pattern "
26+
+ "at index " + (i - j));
27+
int index = (i - j);
28+
j = lps[j - 1];
29+
return index;
30+
31+
}
32+
33+
// mismatch after j matches
34+
else if (i < N && pat.charAt(j) != txt.charAt(i)) {
35+
// Do not match lps[0..lps[j-1]] characters,
36+
// they will match anyway
37+
if (j != 0)
38+
j = lps[j - 1];
39+
else
40+
i = i + 1;
41+
}
42+
}
43+
System.out.println("No pattern found");
44+
return -1;
45+
}
46+
47+
void computeLPSArray(String pat, int M, int lps[])
48+
{
49+
// length of the previous longest prefix suffix
50+
int len = 0;
51+
int i = 1;
52+
lps[0] = 0; // lps[0] is always 0
53+
54+
// the loop calculates lps[i] for i = 1 to M-1
55+
while (i < M) {
56+
if (pat.charAt(i) == pat.charAt(len)) {
57+
len++;
58+
lps[i] = len;
59+
i++;
60+
}
61+
else // (pat[i] != pat[len])
62+
{
63+
// This is tricky. Consider the example.
64+
// AAACAAAA and i = 7. The idea is similar
65+
// to search step.
66+
if (len != 0) {
67+
len = lps[len - 1];
68+
69+
// Also, note that we do not increment
70+
// i here
71+
}
72+
else // if (len == 0)
73+
{
74+
lps[i] = len;
75+
i++;
76+
}
77+
}
78+
}
79+
}
80+
81+
82+
}
83+
// This code has been contributed by Amit Khandelwal.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
2+
package com.thealgorithms.searches;
3+
4+
import org.junit.jupiter.api.Test;
5+
import static org.junit.jupiter.api.Assertions.*;
6+
7+
class KMPSearchTest {
8+
9+
@Test
10+
// valid test case
11+
public void KMPSearchTestLast() {
12+
String txt = "ABABDABACDABABCABAB";
13+
String pat = "ABABCABAB";
14+
KMPSearch kmpSearch = new KMPSearch();
15+
int value = kmpSearch.KMPSearch(pat, txt);
16+
System.out.println(value);
17+
assertEquals(value, 10);
18+
19+
}
20+
21+
@Test
22+
// valid test case
23+
public void KMPSearchTestFront() {
24+
String txt = "AAAAABAAABA";
25+
String pat = "AAAA";
26+
KMPSearch kmpSearch = new KMPSearch();
27+
int value = kmpSearch.KMPSearch(pat, txt);
28+
System.out.println(value);
29+
assertEquals(value, 0);
30+
31+
}
32+
33+
@Test
34+
// valid test case
35+
public void KMPSearchTestMiddle() {
36+
String txt = "AAACAAAAAC";
37+
String pat = "AAAA";
38+
KMPSearch kmpSearch = new KMPSearch();
39+
int value = kmpSearch.KMPSearch(pat, txt);
40+
System.out.println(value);
41+
assertEquals(value, 4);
42+
43+
}
44+
@Test
45+
// valid test case
46+
public void KMPSearchTestNotFound() {
47+
String txt = "AAABAAAA";
48+
String pat = "AAAA";
49+
KMPSearch kmpSearch = new KMPSearch();
50+
int value = kmpSearch.KMPSearch(pat, txt);
51+
System.out.println(value);
52+
assertEquals(value, 4);
53+
54+
}
55+
@Test
56+
// not valid test case
57+
public void KMPSearchTest4() {
58+
String txt = "AABAAA";
59+
String pat = "AAAA";
60+
KMPSearch kmpSearch = new KMPSearch();
61+
int value = kmpSearch.KMPSearch(pat, txt);
62+
System.out.println(value);
63+
assertEquals(value, -1);
64+
65+
}
66+
}

0 commit comments

Comments
 (0)