From 5970f4fb97026a43bb28cc880448f314c3465764 Mon Sep 17 00:00:00 2001 From: jackfiled Date: Mon, 1 Jul 2024 11:43:50 +0800 Subject: [PATCH] 20240701 Finished --- .cargo/{config => config.toml} | 0 src/problem/mod.rs | 3 +- ...ign_add_and_search_words_data_structure.rs | 131 ++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) rename .cargo/{config => config.toml} (100%) create mode 100644 src/problem/p211_design_add_and_search_words_data_structure.rs diff --git a/.cargo/config b/.cargo/config.toml similarity index 100% rename from .cargo/config rename to .cargo/config.toml diff --git a/src/problem/mod.rs b/src/problem/mod.rs index d718ef5..9460a11 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -162,4 +162,5 @@ mod p210_course_schedule_ii; mod p909_snakes_and_ladders; mod p433_minimum_genetic_mutation; mod p127_word_ladder; -mod p208_implement_trie_prefix_tree; \ No newline at end of file +mod p208_implement_trie_prefix_tree; +mod p211_design_add_and_search_words_data_structure; \ No newline at end of file diff --git a/src/problem/p211_design_add_and_search_words_data_structure.rs b/src/problem/p211_design_add_and_search_words_data_structure.rs new file mode 100644 index 0000000..1a02d42 --- /dev/null +++ b/src/problem/p211_design_add_and_search_words_data_structure.rs @@ -0,0 +1,131 @@ +/** + * [211] Design Add and Search Words Data Structure + */ +pub struct Solution {} + +// submission codes start here +use std::{rc::Rc, cell::RefCell, collections::{HashMap, VecDeque}}; + +struct TireNode { + is_word: bool, + next: HashMap>>, +} + +impl TireNode { + fn new(is_word: bool) -> Self { + TireNode { + is_word, + next: HashMap::new(), + } + } +} + +struct WordDictionary { + dummy_head: Rc>, +} + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl WordDictionary { + fn new() -> Self { + WordDictionary { + dummy_head: Rc::new(RefCell::new(TireNode::new(false))) + } + } + + fn add_word(&self, word: String) { + let mut node = Rc::clone(&self.dummy_head); + + for (i, c) in word.chars().enumerate() { + if node.borrow().next.contains_key(&c) { + if i == word.len() - 1 { + node.borrow().next + .get(&c) + .unwrap() + .borrow_mut().is_word = true; + } + } else { + if i == word.len() - 1 { + node.borrow_mut().next.insert(c, Rc::new(RefCell::new(TireNode::new(true)))); + } else { + node.borrow_mut().next.insert(c, Rc::new(RefCell::new(TireNode::new(false)))); + } + } + + let tmp_node = Rc::clone(node.borrow().next.get(&c).unwrap()); + node = tmp_node; + } + } + + fn search(&self, word: String) -> bool { + let mut queue = VecDeque::new(); + queue.push_back(Rc::clone(&self.dummy_head)); + + for (i, c) in word.chars().enumerate() { + if queue.is_empty() { + break; + } + + let length = queue.len(); + + for _ in 0..length { + let node = queue.pop_front().unwrap(); + + if i == word.len() - 1 { + if c == '.' && node.borrow().next.iter().any(|(_, n)| { + n.borrow().is_word + }) { + return true; + } + + if let Some(n) = node.borrow().next.get(&c) { + if n.borrow().is_word { + return true; + } + } + } else { + if c == '.' { + for n in node.borrow().next.values() { + queue.push_back(Rc::clone(n)); + } + } else { + if let Some(n) = node.borrow().next.get(&c) { + queue.push_back(Rc::clone(n)); + } + } + } + } + } + + false + } +} + +/** + * Your WordDictionary object will be instantiated and called as such: + * let obj = WordDictionary::new(); + * obj.add_word(word); + * let ret_2: bool = obj.search(word); + */ + +// submission codes end +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_211() { + let mut dict = WordDictionary::new(); + + dict.add_word("bad".to_owned()); + dict.add_word("dad".to_owned()); + dict.add_word("add".to_owned()); + + assert!(!dict.search("pad".to_owned())); + assert!(!dict.search("a".to_owned())); + assert!(dict.search("dad".to_owned())); + assert!(dict.search(".ad".to_owned())); + } +}