Skip to content

Commit bf8b17a

Browse files
authored
Add boyer moore search (TheAlgorithms#389)
1 parent d293d41 commit bf8b17a

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ These are for demonstration purposes only.
114114
## [Strings](./src/string)
115115

116116
- [x] [Aho-Corasick Algorithm](./src/string/aho_corasick.rs)
117+
- [x] [Boyer-Moore String Search Algorithm](./src/string/boyer_moore_search.rs)
117118
- [x] [Burrows-Wheeler transform](./src/string/burrows_wheeler_transform.rs)
118119
- [x] [Knuth Morris Pratt](./src/string/knuth_morris_pratt.rs)
119120
- [x] [Manacher](./src/string/manacher.rs)

src/string/boyer_moore_search.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// In computer science, the Boyer–Moore string-search algorithm is an efficient string-searching algorithm,
2+
// that is the standard benchmark for practical string-search literature. Source: https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm
3+
4+
use std::collections::HashMap;
5+
6+
pub fn boyer_moore_search(text: &str, pattern: &str) -> Vec<usize> {
7+
let mut positions = Vec::new();
8+
let n = text.len() as i32;
9+
let m = pattern.len() as i32;
10+
let pattern: Vec<char> = pattern.chars().collect();
11+
let text: Vec<char> = text.chars().collect();
12+
if n == 0 || m == 0 {
13+
return positions;
14+
}
15+
let mut collection = HashMap::new();
16+
for (i, c) in pattern.iter().enumerate() {
17+
collection.insert(c, i as i32);
18+
}
19+
let mut shift: i32 = 0;
20+
while shift <= (n - m) as i32 {
21+
let mut j = (m - 1) as i32;
22+
while j >= 0 && pattern[j as usize] == text[(shift + j) as usize] {
23+
j -= 1;
24+
}
25+
if j < 0 {
26+
positions.push(shift as usize);
27+
let add_to_shift = {
28+
if (shift + m) < n {
29+
let c = text[(shift + m) as usize];
30+
let index = collection.get(&c).unwrap_or(&-1);
31+
m - index
32+
} else {
33+
1
34+
}
35+
};
36+
shift += add_to_shift;
37+
} else {
38+
let c = text[(shift + j) as usize];
39+
let index = collection.get(&c).unwrap_or(&-1);
40+
let add_to_shift = std::cmp::max(1, j - index);
41+
shift += add_to_shift;
42+
}
43+
}
44+
positions
45+
}
46+
47+
#[cfg(test)]
48+
mod tests {
49+
use super::*;
50+
51+
#[test]
52+
fn test_boyer_moore_search() {
53+
let a = boyer_moore_search("AABCAB12AFAABCABFFEGABCAB", "ABCAB");
54+
assert_eq!(a, [1, 11, 20]);
55+
let a = boyer_moore_search("AABCAB12AFAABCABFFEGABCAB", "FFF");
56+
assert_eq!(a, []);
57+
let a = boyer_moore_search("AABCAB12AFAABCABFFEGABCAB", "CAB");
58+
assert_eq!(a, [3, 13, 22]);
59+
}
60+
}

src/string/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod aho_corasick;
2+
mod boyer_moore_search;
23
mod burrows_wheeler_transform;
34
mod hamming_distance;
45
mod jaro_winkler_distance;
@@ -12,6 +13,7 @@ mod suffix_tree;
1213
mod z_algorithm;
1314

1415
pub use self::aho_corasick::AhoCorasick;
16+
pub use self::boyer_moore_search::boyer_moore_search;
1517
pub use self::burrows_wheeler_transform::{
1618
burrows_wheeler_transform, inv_burrows_wheeler_transform,
1719
};

0 commit comments

Comments
 (0)