实现一个魔法字典
前缀树存储单词。然后对要查询的每个单词,对它的每个位置去替代一个不同的字符,然后去字典树里面查询存在与否即可。
class MagicDictionary {
struct Node{
bool isEnd=false;
Node* children[26] = {0};
};
Node* root = nullptr;
void insert(const string& s){
Node* p = root;
for(char c:s){
if(!p->children[c-'a']){
p->children[c-'a'] = new Node;
}
p = p->children[c-'a'];
}
p->isEnd = true;
}
bool ask(const string& s){
Node* p = root;
for(char c:s){
if(!p->children[c-'a']){
return false;
}
p = p->children[c-'a'];
}
return p->isEnd;
}
public:
/** Initialize your data structure here. */
MagicDictionary() {
root = new Node;
}
/** Build a dictionary through a list of words */
void buildDict(vector<string> dict) {
for(string& s:dict){
insert(s);
}
}
/** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
bool search(string word) {
for(int i=0;i<word.size();i++){
char old = word[i];
for(char c='a';c<='z';c++){
if(old==c){
continue;
}
word[i] = c;
if(ask(word)){
return true;
}
}
word[i] = old;
}
return false;
}
};
/**
* Your MagicDictionary object will be instantiated and called as such:
* MagicDictionary* obj = new MagicDictionary();
* obj->buildDict(dict);
* bool param_2 = obj->search(word);
*/
DFS优化版、省去一些冗余的比较:
其余的代码没有改变,只是查找的时候用dfs实现,状态转移量Node*,int idx
,过程量int changed
。只有当搜索到字符串的终点,并且恰好变化了一次,并且节点是某个字符串的结尾,才能返回true。
注意一个剪枝:如果changed>1
立即回溯。
class MagicDictionary {
struct Node{
bool isEnd=false;
Node* children[26] = {0};
};
Node* root = nullptr;
void insert(const string& s){
Node* p = root;
for(char c:s){
if(!p->children[c-'a']){
p->children[c-'a'] = new Node;
}
p = p->children[c-'a'];
}
p->isEnd = true;
}
bool ask(const string& s){
return dfs(s,root,0,0);
}
bool dfs(const string& s,Node* p,int idx,int changed){
if(idx==s.size() && changed==1 && p->isEnd){
return true;
}
if(changed>1){
return false;
}
for(int i=0;i<26;i++){
if(p->children[i]){
if(i==s[idx]-'a'){
if(dfs(s,p->children[i],idx+1,changed)){
return true;
}
}else{
if(dfs(s,p->children[i],idx+1,changed+1)){
return true;
}
}
}
}
return false;
}
public:
MagicDictionary() {
root = new Node;
}
void buildDict(vector<string> dict) {
for(string&s:dict){
insert(s);
}
}
bool search(string word) {
return ask(word);
}
};
这题测试数据太水了,这都可以过。
class MagicDictionary {
public:
set<string> st;
/** Initialize your data structure here. */
MagicDictionary() {//构造函数
}
/** Build a dictionary through a list of words */
void buildDict(vector<string> dict) {
for(int i = 0; i < dict.size(); i++){
st.insert(dict[i]);
}
}
/** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
bool search(string word) {
if(st.empty()) return false;
for(auto str : st){
if(str.size() != word.size()) continue;
if(str == word) continue;
if(is_changed(str, word)) return true;
}
return false;
}
bool is_changed(string str1, string str2){
int length = str1.size();
int cnt = 0;
for(int i = 0; i < length; i++){
if(str1[i] != str2[i]) cnt++;
}
if(cnt == 1) return true;
else return false;
}
};
/**
* Your MagicDictionary object will be instantiated and called as such:
* MagicDictionary* obj = new MagicDictionary();
* obj->buildDict(dict);
* bool param_2 = obj->search(word);
*/