Design a data structure that supports the following two operations:
void addWord(word) bool search(word)
search(word) can search a literal word or a regular expression string containing only letters a-z
or .
. A .
means it can represent any one letter.
Example:
addWord("bad") addWord("dad") addWord("mad") search("pad") -> false search("bad") -> true search(".ad") -> true search("b..") -> true
Note:
You may assume that all words are consist of lowercase letters a-z
.
题解:可以用trie树也可以用map,trie树要注意search时遇到'.'时要遍历孩子26个节点中非空的那些,只要其中为true即可也就是说就算结果是false也不能直接return false要用res记录所有结果的并集只要其中一个true即可,这是用dfs带有目标string的遍历指针的写法;也可以直接不用index,在dfs里面直接遍历string,然后遇到.才递归,这种情况要注意回溯的情况因为回溯的最终出口就是非递归情况的指针root,所以要return root->isword,前面我最后也写了这句话但是错了因为这是前面所有递归出来的结果也就是前面没有return的那些dfs递归回溯到开始时的root,正确应该是最初那些就应该return,然后出口直接在开头判断index是不是到达string结尾;最快的是map,也就是把长度相同映射到同一个map,然后写个判断长度相同是否相等的方法,思路更加简单了,因为对'.'的处理只要是‘.’的情况都是当成通用符
代码:
//直接dfs里面遍历版本
class TrieNode{
public:
bool isWord;
TrieNode* child[26];
TrieNode():isWord(false){
memset(child, NULL, sizeof(TrieNode*) * 26);
}
};
class WordDictionary {
public:
/** Initialize your data structure here. */
WordDictionary() {
root=new TrieNode();
}
/** Adds a word into the data structure. */
void addWord(string word) {
TrieNode* p=root;
for(auto a:word){
int i=a-'a';
if(p->child[i]==nullptr) p->child[i]=new TrieNode();
p=p->child[i];
}
p->isWord=true;
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
bool search(string word) {
return dfs(word,root);
}
bool dfs(string word,TrieNode* root){
for(int i=0;i<word.size();i++){
int k=word[i]-'a';
if(word[i]!='.'){
if(!root->child[k]) return false;
root=root->child[k];
}else{
bool res=false;
for(int j=0;j<26;j++){
if(root->child[j]) res|=dfs(word.substr(i+1),root->child[j]) ;
}
return res;
}
}
return root->isWord;
}
private:
TrieNode* root;
};
//dfs里面没有遍历的版本
class TrieNode{
public:
bool isWord;
TrieNode* child[26];
TrieNode():isWord(false){
memset(child, NULL, sizeof(TrieNode*) * 26);
}
};
class WordDictionary {
public:
/** Initialize your data structure here. */
WordDictionary() {
root=new TrieNode();
}
/** Adds a word into the data structure. */
void addWord(string word) {
TrieNode* p=root;
for(auto a:word){
int i=a-'a';
if(p->child[i]==nullptr) p->child[i]=new TrieNode();
p=p->child[i];
}
p->isWord=true;
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
bool search(string word) {
return dfs(word,0,root);
}
bool dfs(string word,int index,TrieNode* root){
if(index==word.size()) return root->isWord;
int i=word[index]-'a';
if(word[index]!='.'&&root->child[i]) return dfs(word,index+1,root->child[i]);
else if(word[index]!='.'&&!root->child[i]) return false;
else{
bool res=false;
for(int j=0;j<26;j++){
if(root->child[j]) res|=dfs(word,index+1,root->child[j]);
}
return res;
}
}
private:
TrieNode* root;
};
//map版本
class WordDictionary {
public:
WordDictionary() {}
void addWord(string word) {
words[word.size()].push_back(word);
}
bool search(string word) {
for(auto s: words[word.size()]) if(isEqual(s, word)) return true;
return false;
}
private:
unordered_map<int, vector<string>>words;
bool isEqual(string a, string b){
for(int i = 0; i < a.size(); i++){
if(b[i] == '.') continue;
if(a[i] != b[i]) return false;
}
return true;
}
};