Skip to content

Commit

Permalink
Add problem 2156: Find Substring With Given Hash Value
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Jul 22, 2024
1 parent 1a0a0a9 commit 86e4370
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,7 @@ pub mod problem_2149_rearrange_array_elements_by_sign;
pub mod problem_2150_find_all_lonely_numbers_in_the_array;
pub mod problem_2154_keep_multiplying_found_values_by_two;
pub mod problem_2155_all_divisions_with_the_highest_score_of_a_binary_array;
pub mod problem_2156_find_substring_with_given_hash_value;
pub mod problem_2160_minimum_sum_of_four_digit_number_after_splitting_digits;
pub mod problem_2161_partition_array_according_to_given_pivot;
pub mod problem_2164_sort_even_and_odd_indices_independently;
Expand Down
80 changes: 80 additions & 0 deletions src/problem_2156_find_substring_with_given_hash_value/iterative.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::num::NonZeroU64;

impl Solution {
fn pow_mod(mut base: u64, mut exponent: u32, modulus: NonZeroU64) -> u64 {
let mut result = 1;

while exponent != 0 {
if exponent & 1 != 0 {
result = (result * base) % modulus;
}

base = (base * base) % modulus;
exponent >>= 1;
}

result
}

pub fn sub_str_hash(s: String, power: i32, modulo: i32, k: i32, hash_value: i32) -> String {
let slice = s.as_bytes();
let power = u64::from(power as u32);
let modulo = NonZeroU64::new(u64::from(modulo as u32)).unwrap();
let k = k as u32 as usize;
let hash_value = hash_value as u32;
let n = slice.len();
let mut current_hash = 0;

for &c in slice[n - k..].iter().rev() {
current_hash = (current_hash * power + u64::from(c - (b'a' - 1))) % modulo;
}

let mut iter = slice.iter().zip(&slice[k..]);
let mut i = n - k;
let mut start = 0;
let base = Self::pow_mod(power, k as u32 - 1, modulo);

loop {
if current_hash as u32 == hash_value {
start = i;
}

if let Some((&new, &old)) = iter.next_back() {
let (new, old) = (new - (b'a' - 1), old - (b'a' - 1));
let old_hash = (base * u64::from(old)) % modulo;

current_hash = ((current_hash + modulo.get() - old_hash) * power + u64::from(new)) % modulo;
i -= 1;
} else {
break;
}
}

let mut result = s;

result.truncate(start + k);
result.replace_range(..start, "");

result
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn sub_str_hash(s: String, power: i32, modulo: i32, k: i32, hash_value: i32) -> String {
Self::sub_str_hash(s, power, modulo, k, hash_value)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
18 changes: 18 additions & 0 deletions src/problem_2156_find_substring_with_given_hash_value/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pub mod iterative;

pub trait Solution {
fn sub_str_hash(s: String, power: i32, modulo: i32, k: i32, hash_value: i32) -> String;
}

#[cfg(test)]
mod tests {
use super::Solution;

pub fn run<S: Solution>() {
let test_cases = [(("leetcode", 7, 20, 2, 0), "ee"), (("fbxzaad", 31, 100, 3, 32), "fbx")];

for ((s, power, modulo, k, hash_value), expected) in test_cases {
assert_eq!(S::sub_str_hash(s.to_string(), power, modulo, k, hash_value), expected);
}
}
}

0 comments on commit 86e4370

Please sign in to comment.