Skip to content

Commit 6b52466

Browse files
Add Abbreviation Dynamic Programming Algorithm
1 parent 13710a7 commit 6b52466

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
* [Union Find](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/union_find.rs)
8888
* [Veb Tree](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/veb_tree.rs)
8989
* Dynamic Programming
90+
* [Abbreviation](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/abbreviation.rs)
9091
* [Coin Change](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/coin_change.rs)
9192
* [Egg Dropping](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/egg_dropping.rs)
9293
* [Fibonacci](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/fibonacci.rs)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//! Abbreviation Problem Solution
2+
//!
3+
//! This module solves the abbreviation problem: determining if string `a` can be
4+
//! transformed into string `b` by capitalizing zero or more lowercase letters and
5+
//! deleting all remaining lowercase letters.
6+
7+
/// Determines if string `a` can be transformed into string `b` by:
8+
/// 1. Capitalizing zero or more lowercase letters in `a`
9+
/// 2. Deleting all remaining lowercase letters
10+
///
11+
/// The solution uses dynamic programming where `dp[i][j]` represents whether
12+
/// the first `i` characters of `a` can form the first `j` characters of `b`.
13+
///
14+
/// # Arguments
15+
/// * `a` - The input string that may contain both uppercase and lowercase letters
16+
/// * `b` - The target string containing only uppercase letters
17+
///
18+
/// # Returns
19+
/// * A boolean indicating whether the transformation is possible
20+
///
21+
/// # Complexity
22+
/// * Time complexity: O(n * m) where n is length of string a and m is length of string b
23+
/// * Space complexity: O(n * m) for the DP table
24+
///
25+
/// # Examples
26+
/// ```
27+
/// use the_algorithms_rust::dynamic_programming::abbreviation;
28+
///
29+
/// assert_eq!(abbreviation("daBcd", "ABC"), true);
30+
/// assert_eq!(abbreviation("dBcd", "ABC"), false);
31+
/// ```
32+
pub fn abbreviation(a: &str, b: &str) -> bool {
33+
let a_chars: Vec<char> = a.chars().collect();
34+
let b_chars: Vec<char> = b.chars().collect();
35+
let n = a_chars.len();
36+
let m = b_chars.len();
37+
38+
// dp[i][j] represents whether first i chars of a can form first j chars of b
39+
let mut dp = vec![vec![false; m + 1]; n + 1];
40+
41+
// Base case: empty string a can form empty string b
42+
dp[0][0] = true;
43+
44+
// Fill the first column: we can form empty b by deleting all lowercase letters
45+
for i in 0..n {
46+
if a_chars[i].is_lowercase() {
47+
dp[i + 1][0] = dp[i][0];
48+
}
49+
}
50+
51+
for i in 0..n {
52+
for j in 0..=m {
53+
if dp[i][j] {
54+
// If we can match current position, check next characters
55+
if j < m && a_chars[i].to_ascii_uppercase() == b_chars[j] {
56+
dp[i + 1][j + 1] = true;
57+
}
58+
59+
// If current character in a is lowercase, we can delete it
60+
if a_chars[i].is_lowercase() {
61+
dp[i + 1][j] = true;
62+
}
63+
}
64+
}
65+
}
66+
67+
dp[n][m]
68+
}
69+
70+
#[cfg(test)]
71+
mod tests {
72+
use super::*;
73+
74+
macro_rules! abbreviation_tests {
75+
($($name:ident: ($a:expr, $b:expr) => $expected:expr,)*) => {
76+
$(
77+
#[test]
78+
fn $name() {
79+
assert_eq!(abbreviation($a, $b), $expected);
80+
}
81+
)*
82+
};
83+
}
84+
85+
abbreviation_tests! {
86+
// Original test cases from the problem
87+
test_daBcd_ABC: ("daBcd", "ABC") => true,
88+
test_dBcd_ABC: ("dBcd", "ABC") => false,
89+
test_AbcE_ABE: ("AbcE", "ABE") => true,
90+
test_AbcE_ABC: ("AbcE", "ABC") => false,
91+
test_abcde_ABCDE: ("abcde", "ABCDE") => true,
92+
test_abcde_ABCD: ("abcde", "ABCD") => false,
93+
test_ABCDE_ABCDE: ("ABCDE", "ABCDE") => true,
94+
test_ABCDE_ABCD: ("ABCDE", "ABCD") => false,
95+
test_aBcDe_ABCDE: ("aBcDe", "ABCDE") => true,
96+
test_aBcDe_ABCD: ("aBcDe", "ABCD") => true,
97+
98+
// Edge test cases
99+
test_empty_both: ("", "") => true,
100+
test_empty_a: ("", "ABC") => false,
101+
test_empty_b: ("abc", "") => true,
102+
test_only_lowercase: ("abc", "ABC") => true,
103+
test_only_uppercase: ("ABC", "ABC") => true,
104+
test_mismatched_uppercase: ("ABD", "ABC") => false,
105+
106+
// Complex cases from HackerRank
107+
test_complex_1: ("LLZOSYAMQRMBTZXTQMQcKGLR", "LLZOSYAMBTZXMQKLR") => false,
108+
test_complex_2: ("MGYXKOVSMAHKOLAZZKWXKS", "MGXKOVSAHKOLZKKDP") => false,
109+
test_complex_3: ("bfBQZcnjXPMNWMZ", "BQZCNJXPMNWMZ") => true,
110+
test_AbcDE_ABDE: ("AbcDE", "ABDE") => true,
111+
test_AbcDE_AFDE: ("AbcDE", "AFDE") => false,
112+
test_ABCD_ABCD: ("ABCD", "ABCD") => true,
113+
test_abcdE_ABCDE: ("abcdE", "ABCDE") => true
114+
}
115+
}

src/dynamic_programming/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod abbreviation;
12
mod coin_change;
23
mod egg_dropping;
34
mod fibonacci;
@@ -19,6 +20,7 @@ mod subset_generation;
1920
mod trapped_rainwater;
2021
mod word_break;
2122

23+
pub use self::abbreviation::abbreviation;
2224
pub use self::coin_change::coin_change;
2325
pub use self::egg_dropping::egg_drop;
2426
pub use self::fibonacci::binary_lifting_fibonacci;

0 commit comments

Comments
 (0)