Skip to content

Commit 0b21bb0

Browse files
authored
Add Boyer-Moore string search algorithm with JUnit tests (#6274)
1 parent 20f0492 commit 0b21bb0

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.thealgorithms.searches;
2+
3+
/**
4+
* Boyer-Moore string search algorithm.
5+
* Efficient algorithm for substring search.
6+
* https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm
7+
*/
8+
public class BoyerMoore {
9+
10+
private final int radix; // Radix (number of possible characters)
11+
private final int[] right; // Bad character rule table
12+
private final String pattern;
13+
14+
public BoyerMoore(String pat) {
15+
this.pattern = pat;
16+
this.radix = 256;
17+
this.right = new int[radix];
18+
19+
for (int c = 0; c < radix; c++) {
20+
right[c] = -1;
21+
}
22+
23+
for (int j = 0; j < pat.length(); j++) {
24+
right[pat.charAt(j)] = j;
25+
}
26+
}
27+
28+
public int search(String text) {
29+
if (pattern.isEmpty()) {
30+
return 0;
31+
}
32+
33+
int m = pattern.length();
34+
int n = text.length();
35+
36+
int skip;
37+
for (int i = 0; i <= n - m; i += skip) {
38+
skip = 0;
39+
for (int j = m - 1; j >= 0; j--) {
40+
char txtChar = text.charAt(i + j);
41+
char patChar = pattern.charAt(j);
42+
if (patChar != txtChar) {
43+
skip = Math.max(1, j - right[txtChar]);
44+
break;
45+
}
46+
}
47+
if (skip == 0) {
48+
return i; // Match found
49+
}
50+
}
51+
52+
return -1; // No match
53+
}
54+
55+
public static int staticSearch(String text, String pattern) {
56+
return new BoyerMoore(pattern).search(text);
57+
}
58+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.thealgorithms.searches;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
public class BoyerMooreTest {
8+
9+
@Test
10+
public void testPatternFound() {
11+
BoyerMoore bm = new BoyerMoore("ABCDABD");
12+
String text = "ABC ABCDAB ABCDABCDABDE";
13+
int index = bm.search(text);
14+
assertEquals(15, index);
15+
}
16+
17+
@Test
18+
public void testPatternNotFound() {
19+
BoyerMoore bm = new BoyerMoore("XYZ");
20+
String text = "ABC ABCDAB ABCDABCDABDE";
21+
int index = bm.search(text);
22+
assertEquals(-1, index);
23+
}
24+
25+
@Test
26+
public void testPatternAtBeginning() {
27+
BoyerMoore bm = new BoyerMoore("ABC");
28+
String text = "ABCDEF";
29+
int index = bm.search(text);
30+
assertEquals(0, index);
31+
}
32+
33+
@Test
34+
public void testPatternAtEnd() {
35+
BoyerMoore bm = new BoyerMoore("CDE");
36+
String text = "ABCDEFGCDE";
37+
int index = bm.search(text);
38+
assertEquals(2, index); // Primera ocurrencia de "CDE"
39+
}
40+
41+
@Test
42+
public void testEmptyPattern() {
43+
BoyerMoore bm = new BoyerMoore("");
44+
String text = "Hello world";
45+
int index = bm.search(text);
46+
assertEquals(0, index);
47+
}
48+
49+
@Test
50+
public void testStaticSearchMethod() {
51+
String text = "ABCDEFGCDE";
52+
int index = BoyerMoore.staticSearch(text, "CDE");
53+
assertEquals(2, index); // Primera ocurrencia de "CDE"
54+
}
55+
}

0 commit comments

Comments
 (0)