Skip to content

Commit

Permalink
Add problem 2014: Longest Subsequence Repeated k Times
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Sep 16, 2024
1 parent f599830 commit bfd9ed5
Show file tree
Hide file tree
Showing 3 changed files with 112 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 @@ -1500,6 +1500,7 @@ pub mod problem_2009_minimum_number_of_operations_to_make_array_continuous;
pub mod problem_2011_final_value_of_variable_after_performing_operations;
pub mod problem_2012_sum_of_beauty_in_the_array;
pub mod problem_2013_detect_squares;
pub mod problem_2014_longest_subsequence_repeated_k_times;
pub mod problem_2016_maximum_difference_between_increasing_elements;
pub mod problem_2017_grid_game;
pub mod problem_2018_check_if_word_can_be_placed_in_crossword;
Expand Down
93 changes: 93 additions & 0 deletions src/problem_2014_longest_subsequence_repeated_k_times/bfs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
pub struct Solution;

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

use std::collections::VecDeque;

impl Solution {
fn is_subsequence(s: &[u8], k: u16, pattern: &[u8]) -> bool {
let mut iter = s.iter();

(0..k).all(|_| pattern.iter().all(|&lhs| iter.any(|&rhs| lhs == rhs)))
}

pub fn longest_subsequence_repeated_k(s: String, k: i32) -> String {
let k = k as u16;
let mut counts = [0_u16; 26];

for c in s.bytes() {
counts[usize::from(c) - usize::from(b'a')] += 1;
}

let mut candidates = [0_u8; 26];
let mut i = 0;

for (c, &count) in (b'a'..).zip(&counts) {
if count >= k {
candidates[i] = c;
i += 1;
}
}

let candidates = &candidates[..i];
let mut queue = VecDeque::from([[0; 8]]);
let mut result_bytes = [0; 8];
let mut length = 0;

loop {
for _ in 0..queue.len() {
let current = queue.pop_front().unwrap();
let mut current_counts = [0_u8; 26];

for &c in &current[..length] {
current_counts[usize::from(c) - usize::from(b'a')] += 1;
}

for &append in candidates {
if counts[usize::from(append) - usize::from(b'a')]
- u16::from(current_counts[usize::from(append) - usize::from(b'a')])
>= k
{
let mut next = current;

next[length] = append;

if Self::is_subsequence(s.as_bytes(), k, &next[..=length]) {
queue.push_back(next);
}
}
}
}

if let Some(&front) = queue.back() {
result_bytes = front;
length += 1;
} else {
break;
}
}

let mut result = s.into_bytes();

result.truncate(length);
result.copy_from_slice(&result_bytes[..length]);

String::from_utf8(result).unwrap()
}
}

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

impl super::Solution for Solution {
fn longest_subsequence_repeated_k(s: String, k: i32) -> String {
Self::longest_subsequence_repeated_k(s, k)
}
}

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

pub trait Solution {
fn longest_subsequence_repeated_k(s: String, k: i32) -> String;
}

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

pub fn run<S: Solution>() {
let test_cases = [(("letsleetcode", 2), "let"), (("bb", 2), "b"), (("ab", 2), "")];

for ((s, k), expected) in test_cases {
assert_eq!(S::longest_subsequence_repeated_k(s.to_string(), k), expected);
}
}
}

0 comments on commit bfd9ed5

Please sign in to comment.