Skip to content

Commit 3a27544

Browse files
committed
Added Replace Words
1 parent 655a275 commit 3a27544

File tree

2 files changed

+119
-1
lines changed

2 files changed

+119
-1
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ pub mod average_of_levels_in_binary_tree; // 637
499499
pub mod maximum_average_subarray_i; // 643
500500

501501
pub mod palindromic_substrings; // 647 ✓
502-
502+
pub mod replace_words; // 648 ✓
503503
pub mod dota2_senate; // 649 ✓
504504

505505
pub mod find_k_closest_elements; // 658

src/replace_words.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
use std::collections::HashMap;
2+
3+
struct DictionaryNode {
4+
value: char,
5+
items: HashMap<char, DictionaryNode>,
6+
ends_at: bool,
7+
word: String,
8+
}
9+
10+
impl DictionaryNode {
11+
12+
fn new(value: char) -> Self {
13+
Self {
14+
value,
15+
items: HashMap::new(),
16+
ends_at: false,
17+
word: String::from(""),
18+
}
19+
}
20+
}
21+
22+
struct Dictionary {
23+
root: DictionaryNode,
24+
}
25+
26+
impl Dictionary {
27+
28+
fn new() -> Self {
29+
Self {
30+
root: DictionaryNode::new('*')
31+
}
32+
}
33+
34+
fn add_word(&mut self, word: String) {
35+
let mut current = &mut self.root;
36+
for letter in word.chars() {
37+
if !current.items.contains_key(&letter) {
38+
let node = DictionaryNode::new(letter);
39+
current.items.insert(letter, node);
40+
}
41+
current = current.items.get_mut(&letter).unwrap();
42+
}
43+
current.ends_at = true;
44+
current.word = word;
45+
}
46+
47+
fn replace_word<'a>(&'a self, word: &'a str) -> &'a str {
48+
let mut result = word;
49+
let mut current = &self.root;
50+
for letter in word.chars() {
51+
if current.items.contains_key(&letter) {
52+
current = &current.items[&letter];
53+
if current.ends_at {
54+
result = &current.word;
55+
break;
56+
}
57+
} else {
58+
break;
59+
}
60+
}
61+
result
62+
}
63+
64+
}
65+
66+
/// In English, we have a concept called root, which can be followed by some other word to form
67+
/// another longer word - let's call this word derivative. For example, when the root `"help"` is
68+
/// followed by the word `"ful"`, we can form a derivative `"helpful"`.
69+
///
70+
/// Given a `dictionary` consisting of many roots and a `sentence` consisting of words separated by
71+
/// spaces, replace all the derivatives in the sentence with the root forming it. If a derivative
72+
/// can be replaced by more than one root, replace it with the root that has the shortest length.
73+
///
74+
/// Return the `sentence` after the replacement.
75+
struct Solution;
76+
77+
impl Solution {
78+
79+
fn to_dictionary(words: Vec<String>) -> Dictionary {
80+
let mut result = Dictionary::new();
81+
for word in words {
82+
result.add_word(word);
83+
}
84+
result
85+
}
86+
87+
pub fn replace_words(dictionary: Vec<String>, sentence: String) -> String {
88+
let dict = Self::to_dictionary(dictionary);
89+
let result: Vec<&str> = sentence
90+
.split(' ')
91+
.map(|word| dict.replace_word(word))
92+
.collect();
93+
result.join(" ")
94+
}
95+
96+
}
97+
98+
#[cfg(test)]
99+
mod tests {
100+
use super::Solution;
101+
102+
#[test]
103+
fn example_1() {
104+
let dictionary = vec![str!("cat"), str!("bat"), str!("rat")];
105+
let sentence = str!("the cattle was rattled by the battery");
106+
let result = Solution::replace_words(dictionary, sentence);
107+
assert_eq!(result, "the cat was rat by the bat");
108+
}
109+
110+
#[test]
111+
fn example_2() {
112+
let dictionary = vec![str!("a"), str!("b"), str!("c")];
113+
let sentence = str!("aadsfasf absbs bbab cadsfafs");
114+
let result = Solution::replace_words(dictionary, sentence);
115+
assert_eq!(result, "a a b c");
116+
}
117+
118+
}

0 commit comments

Comments
 (0)