这个题目跟208相似,但是其中有一个细节需要注意,让我纠结了半天。
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
class DictNode{
public:
char c;
DictNode* next[26];
bool isWord;
DictNode(char _c):c(_c),isWord(false){
memset(next,0,sizeof(DictNode*) * 26);
}
DictNode():isWord(false){
memset(next,0,sizeof(DictNode*) * 26);
}
};
class WordDictionary {
public:
//constructor
WordDictionary(){
root = new DictNode();
}
// Adds a word into the data structure.
void addWord(string word) {
DictNode* p = root;
for(int i = 0 ; i < word.size() ; ++i ){
char c = word[i];
int idx = c - 'a';
if(!p->next[idx]){
p->next[idx] = new DictNode(c);
}
p = p -> next[idx];
}
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 searchHelper(root,word.c_str());
}
private:
DictNode* root;
bool searchHelper(DictNode* now,const char* s){
DictNode* p =now;
for(int i = 0; i < strlen(s); ++i){
if(p && s[i] == '.'){
DictNode* x = p; //*
for(int j = 0;j < 26 ; ++j){
p = x->next[j]; //*
if(searchHelper(p,s+i+1)) return true;//*
//DictNode* x = p->next[j];
//if(searchHelper(x,s+i+1)) return true;
}
}else if(p && s[i] != '.'){
int idx = s[i] - 'a';
p = p -> next[idx];
}else{
break;
}
}
return p && p->isWord;
}
};
// Your WordDictionary object will be instantiated and called as such:
// WordDictionary wordDictionary;
// wordDictionary.addWord("word");
// wordDictionary.search("pattern");
int main(){
WordDictionary wordDictionary;
wordDictionary.addWord("a");
bool t = wordDictionary.search("a.");
cout<< t << endl;
}
注意带//*号附近的代码
DictNode* x = p;//*
for(int j = 0;j < 26 ; ++j){
p = x->next[j]; //*
if(searchHelper(p,s+i+1)) return true;//*
//DictNode* x = p->next[j];
//if(searchHelper(x,s+i+1)) return true;
如果将带星号的代码行去掉,将后两行的注释去掉,那么好像代码也没有问题,都是在这个地方需要遍历p节点的next数组,但是后面的两行其实是不正确的!
原因在于,星号行的代码执行后,p就被改变了,但是写成最后两行的样式,那么p是无论如何不会改变的,这样的话,字典树的整个遍历就在这个地方卡住了,如果字典中有”a”,而待查找的字符串为”a.”,那么用最后两行的写法就会输出true,但是明显应该是false,长度都不同。
果然自己还是渣,慢慢练吧。