###### tags: `Leetcode` `medium` `design` `hash` `python` `c++` # 211. Design Add and Search Words Data Structure ## [題目連結:] https://leetcode.com/problems/design-add-and-search-words-data-structure/ ## 題目: Design a data structure that supports adding new words and finding if a string matches any previously added string. Implement the ```WordDictionary``` class: * ```WordDictionary()``` Initializes the object. * ```void addWord(word)``` Adds ```word``` to the data structure, it can be matched later. * ```bool search(word)``` Returns ```true``` if there is any string in the data structure that matches ```word``` or ```false``` otherwise. ```word``` may contain dots ```'.'``` where dots can be matched with any letter. **Example:** ``` Input ["WordDictionary","addWord","addWord","addWord","search","search","search","search"] [[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]] Output [null,null,null,null,false,true,true,true] Explanation WordDictionary wordDictionary = new WordDictionary(); wordDictionary.addWord("bad"); wordDictionary.addWord("dad"); wordDictionary.addWord("mad"); wordDictionary.search("pad"); // return False wordDictionary.search("bad"); // return True wordDictionary.search(".ad"); // return True wordDictionary.search("b.."); // return True ``` ## 解題想法: * 同概念題目: [208. Implement Trie (Prefix Tree)](/RFOtQ4WeRXiUxREkhkCKBA) * 實作字典樹(前綴樹) * 額外條件: **' . '** 能做為任何字母 * 字典樹的每一個node皆是map: * key: 當前字母 * val: map,所有與當前字母有關聯的下個字母 * **若當前字母為某單詞的結尾,則在其val中新增一個key為"#"** ## Python: ``` python= #類似P208 class WordDictionary(object): def __init__(self): self.root={} def addWord(self, word): """ :type word: str :rtype: None """ curMap = self.root for char in word: if char not in curMap: curMap[char]={} curMap=curMap[char] #當為單詞尾加上個'#' curMap['#']=True def search(self, word): """ :type word: str :rtype: bool """ return self.dfs(self.root,word,pos=0) def dfs(self,curMap,word,pos): if pos==len(word): return True if '#' in curMap else False #若有'#'才表示為一個完整單詞 #當遇到萬用'.'時 往後拜訪其他正常char elif word[pos]=='.': for child in curMap: #不能是'#' 才能往下遍歷正常的char if child!='#' and self.dfs(curMap[child],word,pos+1): return True return False elif word[pos] not in curMap: return False else: #正常往後拜訪 return self.dfs(curMap[word[pos]],word,pos+1) # Your WordDictionary object will be instantiated and called as such: # obj = WordDictionary() # obj.addWord(word) # param_2 = obj.search(word) res = WordDictionary() res.addWord("bad") res.addWord("dad") res.addWord("mad") print(res.search("pad")) print(res.search("bad")) print(res.search(".ad")) ``` ## C++: ``` cpp= #include<bits/stdc++.h> using namespace std; class TrieNode{ public: TrieNode* childMap[26]; bool wordEnd; TrieNode(): wordEnd(false){ for (auto& child: childMap) child=nullptr; } }; class WordDictionary { public: WordDictionary() { root= new TrieNode(); } void addWord(string word) { TrieNode* curMap=root; for (char val: word){ int num=val-'a'; if (!curMap->childMap[num]) curMap->childMap[num]=new TrieNode(); curMap=curMap->childMap[num]; } curMap->wordEnd=true; } bool search(string word) { return dfs(root,word,0); } //string call by reference '&' bool dfs(TrieNode* curMap, string& word, int pos){ if (pos==word.size()) return curMap->wordEnd; else if (word[pos]=='.'){ for (auto& child: curMap->childMap){ if (child && dfs(child, word, pos+1)) return true; } return false; } else if (!curMap->childMap[word[pos]-'a']) return false; else return dfs(curMap->childMap[word[pos]-'a'],word,pos+1); } private: TrieNode* root; }; int main(){ WordDictionary* res=new WordDictionary(); res->addWord("bad"); res->addWord("dad"); res->addWord("mad"); bool ans1=res->search("pad"); //0 bool ans2=res->search("bad"); //1 bool ans3=res->search(".ad"); //1 cout<<ans1<<" "<<ans2<<" "<<ans3<<endl; return 0; } ```