Skip to content

Commit 0e681b7

Browse files
committed
Add problem 3335: Total Characters in String After Transformations I
1 parent 5c4cb12 commit 0e681b7

File tree

4 files changed

+164
-0
lines changed

4 files changed

+164
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,7 @@ pub mod problem_3326_minimum_division_operations_to_make_array_non_decreasing;
21952195
pub mod problem_3330_find_the_original_typed_string_i;
21962196
pub mod problem_3332_maximum_points_tourist_can_earn;
21972197
pub mod problem_3334_find_the_maximum_factor_score_of_array;
2198+
pub mod problem_3335_total_characters_in_string_after_transformations_i;
21982199
pub mod problem_3350_adjacent_increasing_subarrays_detection_ii;
21992200

22002201
#[cfg(test)]
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
pub struct Solution;
2+
3+
// ------------------------------------------------------ snip ------------------------------------------------------ //
4+
5+
impl Solution {
6+
fn add(mut lhs: u32, rhs: u32) -> u32 {
7+
const MODULUS: u32 = 1_000_000_007;
8+
9+
lhs += rhs;
10+
11+
lhs.checked_sub(MODULUS).unwrap_or(lhs)
12+
}
13+
14+
pub fn length_after_transformations(s: String, t: i32) -> i32 {
15+
let t = t.cast_unsigned() as usize;
16+
let mut counts = [0_u32; 26];
17+
18+
for c in s.bytes() {
19+
counts[usize::from(c) - usize::from(b'a')] += 1;
20+
}
21+
22+
let mut cursor = 0_usize;
23+
24+
for _ in 0..t {
25+
let next_cursor = cursor.checked_sub(1).unwrap_or(25);
26+
27+
counts[cursor] = Self::add(counts[cursor], counts[next_cursor]);
28+
cursor = next_cursor;
29+
}
30+
31+
counts.iter().copied().fold(0, Self::add).cast_signed()
32+
}
33+
}
34+
35+
// ------------------------------------------------------ snip ------------------------------------------------------ //
36+
37+
impl super::Solution for Solution {
38+
fn length_after_transformations(s: String, t: i32) -> i32 {
39+
Self::length_after_transformations(s, t)
40+
}
41+
}
42+
43+
#[cfg(test)]
44+
mod tests {
45+
#[test]
46+
fn test_solution() {
47+
super::super::tests::run::<super::Solution>();
48+
}
49+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
pub struct Solution;
2+
3+
// ------------------------------------------------------ snip ------------------------------------------------------ //
4+
5+
use std::array;
6+
7+
impl Solution {
8+
const MODULUS: u64 = 1_000_000_007;
9+
10+
fn matrix_multiply(lhs: &[[u32; 26]; 26], rhs: &[[u32; 26]; 26]) -> [[u32; 26]; 26] {
11+
let mut result = [[0; 26]; 26];
12+
13+
result.iter_mut().zip(lhs).for_each(|(target_row, lhs_row)| {
14+
for (i, target) in target_row.iter_mut().enumerate() {
15+
*target = lhs_row.iter().zip(rhs).fold(0, |sum, (&lhs_value, rhs_row)| {
16+
(sum + u64::from(lhs_value) * u64::from(rhs_row[i])) % Self::MODULUS
17+
}) as _;
18+
}
19+
});
20+
21+
result
22+
}
23+
24+
fn exp_mod(mut base: [[u32; 26]; 26], mut exponent: u32) -> [[u32; 26]; 26] {
25+
while exponent & 1 == 0 {
26+
base = Self::matrix_multiply(&base, &base);
27+
exponent >>= 1;
28+
}
29+
30+
if exponent == 1 {
31+
return base;
32+
}
33+
34+
let mut result = base;
35+
36+
loop {
37+
exponent >>= 1;
38+
base = Self::matrix_multiply(&base, &base);
39+
40+
if exponent & 1 != 0 {
41+
result = Self::matrix_multiply(&result, &base);
42+
43+
if exponent == 1 {
44+
break;
45+
}
46+
}
47+
}
48+
49+
result
50+
}
51+
52+
pub fn length_after_transformations(s: String, t: i32) -> i32 {
53+
let base = array::from_fn(|i| {
54+
let mut result = [0; 26];
55+
56+
result[25] = u32::from(i < 2);
57+
58+
if i != 0 {
59+
result[i - 1] = 1;
60+
}
61+
62+
result
63+
});
64+
65+
let matrix = Self::exp_mod(base, t.cast_unsigned());
66+
67+
let mut counts = [0_u32; 26];
68+
69+
for c in s.bytes() {
70+
counts[usize::from(c) - usize::from(b'a')] += 1;
71+
}
72+
73+
matrix.iter().fold(0, |sum, row| {
74+
row.iter().zip(&counts).fold(sum, |sum, (&lhs, &rhs)| {
75+
(sum + u64::from(lhs) * u64::from(rhs)) % Self::MODULUS
76+
})
77+
}) as _
78+
}
79+
}
80+
81+
// ------------------------------------------------------ snip ------------------------------------------------------ //
82+
83+
impl super::Solution for Solution {
84+
fn length_after_transformations(s: String, t: i32) -> i32 {
85+
Self::length_after_transformations(s, t)
86+
}
87+
}
88+
89+
#[cfg(test)]
90+
mod tests {
91+
#[test]
92+
fn test_solution() {
93+
super::super::tests::run::<super::Solution>();
94+
}
95+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
pub mod dynamic_programming;
2+
pub mod matrix_multiplication;
3+
4+
pub trait Solution {
5+
fn length_after_transformations(s: String, t: i32) -> i32;
6+
}
7+
8+
#[cfg(test)]
9+
mod tests {
10+
use super::Solution;
11+
12+
pub fn run<S: Solution>() {
13+
let test_cases = [(("abcyy", 2), 7), (("azbk", 1), 5)];
14+
15+
for ((s, t), expected) in test_cases {
16+
assert_eq!(S::length_after_transformations(s.to_string(), t), expected);
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)