diff --git a/rust/34_string/kmp.rs b/rust/34_string/kmp.rs new file mode 100644 index 0000000..6731994 --- /dev/null +++ b/rust/34_string/kmp.rs @@ -0,0 +1,58 @@ +fn kmp_search(primary: &str, pattern: &str) -> Vec { + if primary.is_empty() || pattern.is_empty() || pattern.len() > primary.len() { return vec![0]; } + + let primary_chars: Vec = primary.chars().collect(); + let pattern_chars: Vec = pattern.chars().collect(); + let max_match_lengths = get_failure_function(pattern); + let mut count = 0; + let m = pattern.len(); + let mut positions = vec![]; + + for i in 0..primary.len() { + while count > 0 && pattern_chars[count as usize] != primary_chars[i] { + count = max_match_lengths[(count-1) as usize]; + } + + if pattern_chars[count as usize] == primary_chars[i] { + count += 1; + } + + if count as usize == m { + positions.push((i - m + 1) as i32); + count = max_match_lengths[(count-1) as usize]; + } + } + + positions +} + +fn get_failure_function(pattern: &str) -> Vec { + let m = pattern.len(); + let mut max_match_lengths: Vec = vec![0; m]; + let mut max_length: i32 = 0; + let pattern_chars: Vec = pattern.chars().collect(); + + for i in 1..m { + while max_length > 0 && pattern_chars[max_length as usize] != pattern_chars[i] { + max_length = max_match_lengths[(max_length-1) as usize]; + } + + if pattern_chars[i] == pattern_chars[max_length as usize] { + max_length += 1; + } + + max_match_lengths[i] = max_length; + } + + max_match_lengths +} + +fn main() { + let primary1 = "abbaabbaaba"; + let pattern1 = "abbaaba"; + println!("{:?}", kmp_search(primary1, pattern1)); // 4 + + let primary = "abc abcdab abcdabcdabde"; + let pattern = "bcdabd"; + println!("{:?}", kmp_search(primary, pattern)); // 16 +}