forked from TheAlgorithms/Rust
-
Notifications
You must be signed in to change notification settings - Fork 1
/
boyer_moore_search.rs
60 lines (56 loc) · 1.98 KB
/
boyer_moore_search.rs
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
// In computer science, the Boyer–Moore string-search algorithm is an efficient string-searching algorithm,
// that is the standard benchmark for practical string-search literature. Source: https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm
use std::collections::HashMap;
pub fn boyer_moore_search(text: &str, pattern: &str) -> Vec<usize> {
let mut positions = Vec::new();
let n = text.len() as i32;
let m = pattern.len() as i32;
let pattern: Vec<char> = pattern.chars().collect();
let text: Vec<char> = text.chars().collect();
if n == 0 || m == 0 {
return positions;
}
let mut collection = HashMap::new();
for (i, c) in pattern.iter().enumerate() {
collection.insert(c, i as i32);
}
let mut shift: i32 = 0;
while shift <= (n - m) {
let mut j = m - 1;
while j >= 0 && pattern[j as usize] == text[(shift + j) as usize] {
j -= 1;
}
if j < 0 {
positions.push(shift as usize);
let add_to_shift = {
if (shift + m) < n {
let c = text[(shift + m) as usize];
let index = collection.get(&c).unwrap_or(&-1);
m - index
} else {
1
}
};
shift += add_to_shift;
} else {
let c = text[(shift + j) as usize];
let index = collection.get(&c).unwrap_or(&-1);
let add_to_shift = std::cmp::max(1, j - index);
shift += add_to_shift;
}
}
positions
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_boyer_moore_search() {
let a = boyer_moore_search("AABCAB12AFAABCABFFEGABCAB", "ABCAB");
assert_eq!(a, [1, 11, 20]);
let a = boyer_moore_search("AABCAB12AFAABCABFFEGABCAB", "FFF");
assert_eq!(a, []);
let a = boyer_moore_search("AABCAB12AFAABCABFFEGABCAB", "CAB");
assert_eq!(a, [3, 13, 22]);
}
}