Skip to content

Commit 41f1930

Browse files
committed
676. Implement Magic Dictionary: AC
1 parent 039b4ae commit 41f1930

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

src/solution/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,3 +489,4 @@ mod s0672_bulb_switcher_ii;
489489
mod s0673_number_of_longest_increasing_subsequence;
490490
mod s0674_longest_continuous_increasing_subsequence;
491491
mod s0675_cut_off_trees_for_golf_event;
492+
mod s0676_implement_magic_dictionary;
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* [0676] Implement Magic Dictionary
3+
*
4+
* Design a data structure that is initialized with a list of different words. Provided a string, you should determine if you can change exactly one character in this string to match any word in the data structure.
5+
* Implement the MagicDictionary class:
6+
*
7+
* MagicDictionary() Initializes the object.
8+
* void buildDict(String[] dictionary) Sets the data structure with an array of distinct strings dictionary.
9+
* bool search(String searchWord) Returns true if you can change exactly one character in searchWord to match any string in the data structure, otherwise returns false.
10+
*
11+
*
12+
* Example 1:
13+
*
14+
* Input
15+
* ["MagicDictionary", "buildDict", "search", "search", "search", "search"]
16+
* [[], [["hello", "leetcode"]], ["hello"], ["hhllo"], ["hell"], ["leetcoded"]]
17+
* Output
18+
* [null, null, false, true, false, false]
19+
* Explanation
20+
* MagicDictionary magicDictionary = new MagicDictionary();
21+
* magicDictionary.buildDict(["hello", "leetcode"]);
22+
* magicDictionary.search("hello"); // return False
23+
* magicDictionary.search("hhllo"); // We can change the second 'h' to 'e' to match "hello" so we return True
24+
* magicDictionary.search("hell"); // return False
25+
* magicDictionary.search("leetcoded"); // return False
26+
*
27+
*
28+
* Constraints:
29+
*
30+
* 1 <= dictionary.length <= 100
31+
* 1 <= dictionary[i].length <= 100
32+
* dictionary[i] consists of only lower-case English letters.
33+
* All the strings in dictionary are distinct.
34+
* 1 <= searchWord.length <= 100
35+
* searchWord consists of only lower-case English letters.
36+
* buildDict will be called only once before search.
37+
* At most 100 calls will be made to search.
38+
*
39+
*/
40+
pub struct Solution {}
41+
42+
// problem: https://leetcode.com/problems/implement-magic-dictionary/
43+
// discuss: https://leetcode.com/problems/implement-magic-dictionary/discuss/?currentPage=1&orderBy=most_votes&query=
44+
45+
// submission codes start here
46+
47+
#[derive(Debug, Clone)]
48+
struct TrieNode {
49+
is_word: bool,
50+
children: Vec<Option<TrieNode>>,
51+
}
52+
53+
impl TrieNode {
54+
fn new() -> Self {
55+
TrieNode {
56+
is_word: false,
57+
children: vec![None; 26],
58+
}
59+
}
60+
}
61+
62+
struct MagicDictionary {
63+
trie: TrieNode,
64+
}
65+
66+
/**
67+
* `&self` means the method takes an immutable reference.
68+
* If you need a mutable reference, change it to `&mut self` instead.
69+
*/
70+
impl MagicDictionary {
71+
fn new() -> Self {
72+
Self {
73+
trie: TrieNode::new(),
74+
}
75+
}
76+
fn build_dict(&mut self, dictionary: Vec<String>) {
77+
for s in &dictionary {
78+
let mut cur = &mut self.trie;
79+
for ch in s.as_bytes() {
80+
if cur.children[(ch - b'a') as usize].is_none() {
81+
cur.children[(ch - b'a') as usize] = Some(TrieNode::new());
82+
}
83+
cur = cur.children[(ch - b'a') as usize].as_mut().unwrap();
84+
}
85+
cur.is_word = true
86+
}
87+
}
88+
89+
fn search(&self, mut search_word: String) -> bool {
90+
fn helper(v: &[u8], trie: &TrieNode) -> bool {
91+
let mut cur = trie;
92+
for ch in v {
93+
if cur.children[(ch - b'a') as usize].is_none() {
94+
return false;
95+
}
96+
cur = cur.children[(ch - b'a') as usize].as_ref().unwrap();
97+
}
98+
cur.is_word
99+
}
100+
let mut v = unsafe { search_word.as_bytes_mut() };
101+
for i in 0..v.len() {
102+
for c in b'a'..=b'z' {
103+
if v[i] == c {
104+
continue;
105+
}
106+
let orig = v[i];
107+
v[i] = c;
108+
if helper(v, &self.trie) {
109+
return true;
110+
}
111+
v[i] = orig;
112+
}
113+
}
114+
false
115+
}
116+
}
117+
118+
/**
119+
* Your MagicDictionary object will be instantiated and called as such:
120+
* let obj = MagicDictionary::new();
121+
* obj.build_dict(dictionary);
122+
* let ret_2: bool = obj.search(searchWord);
123+
*/
124+
125+
// submission codes end
126+
127+
#[cfg(test)]
128+
mod tests {
129+
use super::*;
130+
131+
#[test]
132+
fn test_0676_example_1() {
133+
let mut dict = MagicDictionary::new();
134+
dict.build_dict(vec!["hello".to_string(), "leetcode".to_string()]);
135+
assert!(!dict.search("hello".to_string()));
136+
assert!(dict.search("hhllo".to_string()));
137+
assert!(!dict.search("hell".to_string()));
138+
assert!(!dict.search("leetcode".to_string()));
139+
}
140+
}

0 commit comments

Comments
 (0)