1
+ /**
2
+ * Performs Boyer-Moore search on a given string with a given pattern
3
+ *
4
+ * <p>./gradlew run -Palgorithm=strings.BoyerMooreStringSearch
5
+ */
1
6
package com .williamfiset .algorithms .strings ;
2
7
8
+ import static java .lang .Math .max ;
9
+ import static java .lang .Math .min ;
3
10
import static java .util .Objects .isNull ;
4
11
5
12
import java .util .ArrayList ;
6
- import java .util .HashMap ;
7
13
import java .util .List ;
8
- import java .util .Map ;
9
14
10
15
public class BoyerMooreStringSearch {
11
16
17
+ private static final int MAX_ALPHABET_SIZE = 256 ;
18
+
12
19
/**
13
20
* Performs Boyer-Moore search on a given string with a given pattern
14
21
*
@@ -24,11 +31,10 @@ public List<Integer> findOccurrences(String text, String pattern) {
24
31
return new ArrayList <>();
25
32
}
26
33
List <Integer > occurrences = new ArrayList <>();
27
- Map < Character , Integer > skipTable = generateSkipTable (pattern );
34
+ int [] skipTable = generateSkipTable (pattern );
28
35
29
- int textIndex = pattern .length () - 1 ;
30
- int patternIndex = pattern .length () - 1 ;
31
- while (textIndex < text .length ()) {
36
+ int n = pattern .length ();
37
+ for (int textIndex = n - 1 , patternIndex = n - 1 ; textIndex < text .length (); ) {
32
38
if (patternIndex >= 0 && pattern .charAt (patternIndex ) == text .charAt (textIndex )) {
33
39
if (patternIndex == 0 ) {
34
40
occurrences .add (textIndex );
@@ -37,23 +43,27 @@ public List<Integer> findOccurrences(String text, String pattern) {
37
43
}
38
44
patternIndex --;
39
45
} else {
40
- textIndex =
41
- textIndex
42
- + pattern .length ()
43
- - Math .min (
44
- Math .max (patternIndex , 0 ),
45
- 1 + skipTable .getOrDefault (text .charAt (textIndex ), 0 ));
46
- patternIndex = pattern .length () - 1 ;
46
+ textIndex += n - min (max (patternIndex , 0 ), 1 + skipTable [text .charAt (textIndex )]);
47
+ patternIndex = n - 1 ;
47
48
}
48
49
}
49
50
return occurrences ;
50
51
}
51
52
52
- private Map < Character , Integer > generateSkipTable (String pattern ) {
53
- Map < Character , Integer > characterIndexMap = new HashMap <>() ;
54
- for (int charIndex = 0 ; charIndex < pattern .length (); charIndex ++) {
55
- characterIndexMap . put ( pattern .charAt (charIndex ), charIndex ) ;
53
+ private int [] generateSkipTable (String pattern ) {
54
+ int [] skipTable = new int [ MAX_ALPHABET_SIZE ] ;
55
+ for (int i = 0 ; i < pattern .length (); i ++) {
56
+ skipTable [( int ) pattern .charAt (i )] = i ;
56
57
}
57
- return characterIndexMap ;
58
+ return skipTable ;
59
+ }
60
+
61
+ public static void main (String [] args ) {
62
+ BoyerMooreStringSearch searcher = new BoyerMooreStringSearch ();
63
+ String t = "ABABAAABAABAB" ;
64
+ String p = "AA" ;
65
+
66
+ // Prints: [4, 5, 8]
67
+ System .out .println (searcher .findOccurrences (t , p ));
58
68
}
59
69
}
0 commit comments