|
| 1 | +use std::collections::HashMap; |
| 2 | + |
| 3 | +fn bf(primary: &str, pattern: &str) -> i32 { |
| 4 | + if primary.is_empty() || pattern.is_empty() || primary.len() < pattern.len() { return -1; } |
| 5 | + |
| 6 | + let primary_chars: Vec<char> = primary.chars().collect(); |
| 7 | + let pattern_chars: Vec<char> = pattern.chars().collect(); |
| 8 | + for i in 0..(primary.len() - pattern.len() + 1) { |
| 9 | + if pattern_chars == primary_chars[i..i + pattern.len()].to_vec() { |
| 10 | + return i as i32; |
| 11 | + } |
| 12 | + } |
| 13 | + -1 |
| 14 | +} |
| 15 | + |
| 16 | +// 通过哈希算法对主串中的 n-m+1 个子串分别求哈希值, |
| 17 | +// 逐个与模式串的哈希值比较大小。如果某个子串的哈希值与模式串相等,那就说明对应的子串和模式串匹配 |
| 18 | +fn rk(primary: &str, pattern: &str) -> i32 { |
| 19 | + if primary.is_empty() || pattern.is_empty() || primary.len() < pattern.len() { return -1; } |
| 20 | + |
| 21 | + let primary_chars: Vec<char> = primary.chars().collect(); |
| 22 | + let pattern_chars: Vec<char> = pattern.chars().collect(); |
| 23 | + let base: i128 = 26; |
| 24 | + let m = pattern.len(); |
| 25 | + let n = primary.len(); |
| 26 | + let mut pow_vec = vec![]; |
| 27 | + let mut hash = HashMap::new(); |
| 28 | + |
| 29 | + // 存储 26 的 n 次方到数组中,方便后面调用 |
| 30 | + for i in 0..m { |
| 31 | + pow_vec.push(base.pow(i as u32)); |
| 32 | + } |
| 33 | + |
| 34 | + // 计算子串的 hash 值 |
| 35 | + let mut p_value = 0; |
| 36 | + for i in 0..m { |
| 37 | + p_value += (pattern_chars[i] as i128 - 'a' as i128) * pow_vec[m-1-i]; |
| 38 | + } |
| 39 | + |
| 40 | + // 计算主串的 n-m+1 个子串的 hash 值 |
| 41 | + for i in 0..(n - m + 1) { |
| 42 | + // 计算主串中 index 为 0 的子串的 hash 值 |
| 43 | + let mut value = 0; |
| 44 | + if i == 0 { |
| 45 | + for i in 0..m { |
| 46 | + value += (primary_chars[i] as i128 - 'a' as i128) * pow_vec[m-1-i]; |
| 47 | + } |
| 48 | + } else { |
| 49 | + // 计算 index 为 i 的子串的 hash 值 |
| 50 | + // 计算公式: hash[i] = (hash[i-1] - 26^(m-1) * (primary_chars[i-1] - 'a')) * 26 + (26^0 * (primary_chars[i+m-1] - 'a')) |
| 51 | + value = (hash[&((i-1) as i32)] - base.pow((m-1) as u32) * (primary_chars[i-1] as i128 - 'a' as i128)) * base + ((primary_chars[i+m-1]) as i128 - 'a' as i128); |
| 52 | + } |
| 53 | + |
| 54 | + // hash 值相等,比较两个串内容是否相等,避免 hash 碰撞 |
| 55 | + if value == p_value && pattern_chars == primary_chars[i..i+m].to_vec() { |
| 56 | + return i as i32; |
| 57 | + } |
| 58 | + |
| 59 | + hash.insert(i as i32, value); |
| 60 | + } |
| 61 | + |
| 62 | + -1 |
| 63 | +} |
| 64 | + |
| 65 | +fn main() { |
| 66 | + let primary = "thequickbrownfoxjumpsoverthelazydog"; |
| 67 | + let pattern = "jump"; |
| 68 | + let result = bf(primary, pattern); |
| 69 | + println!("{}", result); // 16 |
| 70 | + |
| 71 | + let result2 = rk(primary, pattern); |
| 72 | + println!("{:?}", result2); // 16 |
| 73 | +} |
0 commit comments