From 330a5720493fab5975f3413747f627e84eaf14fe Mon Sep 17 00:00:00 2001 From: EFanZh Date: Thu, 9 May 2024 13:34:33 +0800 Subject: [PATCH] Add problem 1910: Remove All Occurrences of a Substring --- src/lib.rs | 1 + .../kmp.rs | 83 +++++++++++++++++++ .../mod.rs | 22 +++++ 3 files changed, 106 insertions(+) create mode 100644 src/problem_1910_remove_all_occurrences_of_a_substring/kmp.rs create mode 100644 src/problem_1910_remove_all_occurrences_of_a_substring/mod.rs diff --git a/src/lib.rs b/src/lib.rs index 5f3384ed..878707f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1414,6 +1414,7 @@ pub mod problem_1903_largest_odd_number_in_string; pub mod problem_1904_the_number_of_full_rounds_you_have_played; pub mod problem_1906_minimum_absolute_difference_queries; pub mod problem_1909_remove_one_element_to_make_the_array_strictly_increasing; +pub mod problem_1910_remove_all_occurrences_of_a_substring; pub mod problem_1911_maximum_alternating_subsequence_sum; pub mod problem_1913_maximum_product_difference_between_two_pairs; pub mod problem_1915_number_of_wonderful_substrings; diff --git a/src/problem_1910_remove_all_occurrences_of_a_substring/kmp.rs b/src/problem_1910_remove_all_occurrences_of_a_substring/kmp.rs new file mode 100644 index 00000000..37bb35b7 --- /dev/null +++ b/src/problem_1910_remove_all_occurrences_of_a_substring/kmp.rs @@ -0,0 +1,83 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + fn compute_kmp_table(s: &[u8]) -> Box<[u16]> { + let mut result = vec![0; s.len()].into_boxed_slice(); + let mut matched = 0; + let mut i = 1; + + while let Some(&c) = s.get(i) { + loop { + if c == s[matched] { + matched += 1; + result[i] = matched as _; + + break; + } else if let Some(&next_matched) = result.get(matched.wrapping_sub(1)) { + matched = usize::from(next_matched); + } else { + break; + } + } + + i += 1; + } + + result + } + + pub fn remove_occurrences(s: String, part: String) -> String { + let mut s = s.into_bytes(); + let part = part.as_bytes(); + let kmp_table = Self::compute_kmp_table(part); + let mut matched = 0; + let mut match_history = Vec::::with_capacity(s.len()); + let mut i = 0; + + while let Some(&c) = s.get(i) { + loop { + if c == part[matched] { + matched += 1; + + break; + } else if let Some(&next_matched) = kmp_table.get(matched.wrapping_sub(1)) { + matched = usize::from(next_matched); + } else { + break; + } + } + + if matched == part.len() { + match_history.truncate(match_history.len() - (part.len() - 1)); + matched = usize::from(match_history.last().copied().unwrap_or_default()); + } else { + s[match_history.len()] = c; + match_history.push(matched as _); + } + + i += 1; + } + + s.truncate(match_history.len()); + + String::from_utf8(s).ok().unwrap() + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn remove_occurrences(s: String, part: String) -> String { + Self::remove_occurrences(s, part) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_1910_remove_all_occurrences_of_a_substring/mod.rs b/src/problem_1910_remove_all_occurrences_of_a_substring/mod.rs new file mode 100644 index 00000000..993cde93 --- /dev/null +++ b/src/problem_1910_remove_all_occurrences_of_a_substring/mod.rs @@ -0,0 +1,22 @@ +pub mod kmp; + +pub trait Solution { + fn remove_occurrences(s: String, part: String) -> String; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + (("daabcbaabcbc", "abc"), "dab"), + (("axxxxyyyyb", "xy"), "ab"), + (("gjzgbpggjzgbpgsvpwdk", "gjzgbpg"), "svpwdk"), + ]; + + for ((s, part), expected) in test_cases { + assert_eq!(S::remove_occurrences(s.to_string(), part.to_string()), expected); + } + } +}