题目:
Design a data structure that is initialized with a list of different words. Provided a string, you should determine if you can change exactly one character in this string to match any word in the data structure.
Implement the MagicDictionary
class:
MagicDictionary()
Initializes the object.void buildDict(String[] dictionary)
Sets the data structure with an array of distinct stringsdictionary
.bool search(String searchWord)
Returnstrue
if you can change exactly one character insearchWord
to match any string in the data structure, otherwise returnsfalse
.
Example 1:
Input ["MagicDictionary", "buildDict", "search", "search", "search", "search"] [[], [["hello", "leetcode"]], ["hello"], ["hhllo"], ["hell"], ["leetcoded"]] Output [null, null, false, true, false, false] Explanation MagicDictionary magicDictionary = new MagicDictionary(); magicDictionary.buildDict(["hello", "leetcode"]); magicDictionary.search("hello"); // return False magicDictionary.search("hhllo"); // We can change the second 'h' to 'e' to match "hello" so we return True magicDictionary.search("hell"); // return False magicDictionary.search("leetcoded"); // return False
Constraints:
1 <= dictionary.length <= 100
1 <= dictionary[i].length <= 100
dictionary[i]
consists of only lower-case English letters.- All the strings in
dictionary
are distinct. 1 <= searchWord.length <= 100
searchWord
consists of only lower-case English letters.buildDict
will be called only once beforesearch
.- At most
100
calls will be made tosearch
.
思路:
这题和211.Design Add and Search Words Data Structure相似,都是字典树题,并且search都因为有个字母会改变而写成递归形式。本题的要点是一个字符串的字母只能改变一次,我们也可以用这个剪枝。首先base case 是当前index已经为字符串长度,这时要检查当前bool值和改变次数。在后面进行递归时,每个字母我们选择改变或者不改变,不改变的话就正常往下递归;但是选择当前改变字母的话可以剪枝,先检查change,即改变次数,如果当前改变次数不为0,即已经改变过,那么就不必往下递归了。
代码:
class MagicDictionary {
public:
MagicDictionary() {
}
void buildDict(vector<string> dictionary) {
for (auto s : dictionary) {
insert(s);
}
}
bool search(string searchWord) {
return check(searchWord, trie, 0, 0);
}
private:
class Trie {
public:
Trie* child[26] = { nullptr };
bool flag = false;
};
Trie* trie = new Trie();
void insert(string& word) {
Trie* tmp = trie;
for (int i = 0; i < word.size(); i++) {
int c = word[i] - 'a';
if (!tmp->child[c]) {
tmp->child[c] = new Trie();
}
tmp = tmp->child[c];
}
tmp->flag = true;
}
bool check(string& word, Trie* tmp, int index, int change) {
if (index == word.size()) {
if (tmp->flag && change == 1)
return true;
else
return false;
}
bool ans = false;
for (int i = 0; i < 26; i++) {
if (!tmp->child[i])
continue;
int c = word[index] - 'a';
if (c == i) {
ans |= check(word, tmp->child[c], index + 1, change);
}
else {
if (change == 0)
ans |= check(word, tmp->child[i], index + 1, change + 1);
}
}
return ans;
}
};
/**
* Your MagicDictionary object will be instantiated and called as such:
* MagicDictionary* obj = new MagicDictionary();
* obj->buildDict(dictionary);
* bool param_2 = obj->search(searchWord);
*/