Algod/string/
rabin_karp.rs1pub fn rabin_karp(target: String, pattern: String) -> Vec<usize> {
2 if target.is_empty() || pattern.is_empty() || pattern.len() > target.len() {
4 return vec![];
5 }
6
7 let string: String = (&pattern[0..pattern.len()]).to_string();
8 let hash_pattern = hash(string.clone());
9 let mut ret = vec![];
10 for i in 0..(target.len() - pattern.len() + 1) {
11 let s = (&target[i..(i + pattern.len())]).to_string();
12 let string_hash = hash(s.clone());
13
14 if string_hash == hash_pattern && s == string {
15 ret.push(i);
16 }
17 }
18 ret
19}
20
21fn hash(mut s: String) -> u16 {
22 let prime: u16 = 101;
23 let last_char = s
24 .drain(s.len() - 1..)
25 .next()
26 .expect("Failed to get the last char of the string");
27 let mut res: u16 = 0;
28 for (i, &c) in s.as_bytes().iter().enumerate() {
29 if i == 0 {
30 res = (c as u16 * 256) % prime;
31 } else {
32 res = (((res + c as u16) % 101) * 256) % 101;
33 }
34 }
35 (res + last_char as u16) % prime
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn hi_hash() {
44 let hash_result = hash("hi".to_string());
45 assert_eq!(hash_result, 65);
46 }
47
48 #[test]
49 fn abr_hash() {
50 let hash_result = hash("abr".to_string());
51 assert_eq!(hash_result, 4);
52 }
53
54 #[test]
55 fn bra_hash() {
56 let hash_result = hash("bra".to_string());
57 assert_eq!(hash_result, 30);
58 }
59
60 #[test]
62 fn each_letter_matches() {
63 let index = rabin_karp("aaa".to_string(), "a".to_string());
64 assert_eq!(index, vec![0, 1, 2]);
65 }
66
67 #[test]
68 fn a_few_separate_matches() {
69 let index = rabin_karp("abababa".to_string(), "ab".to_string());
70 assert_eq!(index, vec![0, 2, 4]);
71 }
72
73 #[test]
74 fn one_match() {
75 let index = rabin_karp("ABC ABCDAB ABCDABCDABDE".to_string(), "ABCDABD".to_string());
76 assert_eq!(index, vec![15]);
77 }
78
79 #[test]
80 fn lots_of_matches() {
81 let index = rabin_karp("aaabaabaaaaa".to_string(), "aa".to_string());
82 assert_eq!(index, vec![0, 1, 4, 7, 8, 9, 10]);
83 }
84
85 #[test]
86 fn lots_of_intricate_matches() {
87 let index = rabin_karp("ababababa".to_string(), "aba".to_string());
88 assert_eq!(index, vec![0, 2, 4, 6]);
89 }
90
91 #[test]
92 fn not_found0() {
93 let index = rabin_karp("abcde".to_string(), "f".to_string());
94 assert_eq!(index, vec![]);
95 }
96
97 #[test]
98 fn not_found1() {
99 let index = rabin_karp("abcde".to_string(), "ac".to_string());
100 assert_eq!(index, vec![]);
101 }
102
103 #[test]
104 fn not_found2() {
105 let index = rabin_karp("ababab".to_string(), "bababa".to_string());
106 assert_eq!(index, vec![]);
107 }
108
109 #[test]
110 fn empty_string() {
111 let index = rabin_karp("".to_string(), "abcdef".to_string());
112 assert_eq!(index, vec![]);
113 }
114}