211. Design Add and Search Words Data Structure
问题:
设计一个字典数据结构,存在以下方法:
- 构造该数据结构变量:WordDictionary
- 加入一个单词:void addWord(word)(该单词的各个字母:a~z)
- 搜索一个单词:bool search(word)(该单词的各个字母:a~z 再加上 .<可匹配任意a~z字母>)
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 Constraints: 1 <= word.length <= 500 word in addWord consists lower-case English letters. word in search consist of '.' or lower-case English letters. At most 50000 calls will be made to addWord and search.
解法:DFS(深度优先搜索)
每次递归:匹配每一个字符。若匹配成功 pos+1,递归匹配下一个字符。
path:要匹配字符串的word,当前匹配到的位置pos
optlists:字典中可选的(待匹配的)所有单词set。
对于本问题,设计字典数据结构:
为了节省搜索时间,利用map,对应一些字符串属性,存储对应的字符串set
unordered_map<int, unordered_map<char, unordered_set<string>>> WD;
解释:
第一次map:key:字符串长度length -> value:所有满足该长度的单词(这里继续使用二次map)。
第二次map:key:单词首字母Headc -> value:所有以该首字母开头的单词。(这里使用set,利于进行存在与否判断)。
⚠️ 注意:本问题中为了快速搜索定位,对于广义匹配字符'.',我们也存入一个key为'.'的第二次map,这里保存满足length的所有字符串
(即为第二次map的总表,所有满足第二次map的单词都会存一份在这里)。
代码参考:
1 class WordDictionary { 2 public: 3 /** Initialize your data structure here. */ 4 WordDictionary() { 5 6 } 7 8 void addWord(string word) { 9 int l = word.length(); 10 char Headc = word[0]; 11 WD[l][Headc].insert(word); 12 WD[l]['.'].insert(word); 13 } 14 15 bool search(string word) { 16 int l = word.length(); 17 char Headc = word[0]; 18 if(!WD[l][Headc].size()) return false; 19 if(WD[l][Headc].count(word)) return true; 20 for(string opt:WD[l][Headc]) { 21 if(DFS(word, opt, 0)) return true; 22 } 23 return false; 24 } 25 private: 26 unordered_map<int, unordered_map<char, unordered_set<string>>> WD; 27 bool isValid(char opt, char word) { 28 if(word=='.') return true; 29 if(word!=opt) return false; 30 return true; 31 } 32 bool DFS(string& word, string& opt, int pos) { 33 if(pos==word.length()) return true; 34 if(isValid(opt[pos], word[pos])) { 35 return DFS(word, opt, pos+1); 36 } 37 return false; 38 } 39 }; 40 41 /** 42 * Your WordDictionary object will be instantiated and called as such: 43 * WordDictionary* obj = new WordDictionary(); 44 * obj->addWord(word); 45 * bool param_2 = obj->search(word); 46 */