一、题目
二、题解
这道题在Acwing题目的基础上添加了'.'这个“通配符”,也是是说在查找的过程中,如果遇到'.'他可以替换为任何字母,就好比打牌炸金花里面的王,可以替换任意牌
class WordDictionary {
public:
int p[1000110][27]; // 模拟Trie树的每一个节点
int cnt[1000110]; // 以该节点节点是否有单词
int idx; // 用于模拟开辟“节点”
WordDictionary() { // 构造函数
idx = 0;
memset(p, 0, sizeof(p));
memset(cnt, 0, sizeof(cnt));
}
~WordDictionary() { // 析构函数
idx = 0;
memset(p, 0, sizeof(p));
memset(cnt, 0, sizeof(cnt));
}
void addWord(string word) { // 添加单词
int cur = 0; // 根节点
for (int x : word) { // 遍历单词进行添加
int childIndex = x - 'a'; // 计算出孩子“节点 ”位置
if (!p[cur][childIndex]) p[cur][childIndex] = ++idx; // 当前根节点没有该孩子节点,就创建
cur = p[cur][childIndex]; // 指向孩子节点继续遍历创建
}
cnt[cur]++; // 以该位置结尾有一个单词
}
bool search(int cur, string word, int i) {
if (i >= word.size()) return cnt[cur]; // 递归出口,判断当前节点是否是某个单词的结尾
for (int j = i; j < word.size(); j++) { // 循环查询
if (word[j] != '.') { // 不是通配符 ‘.’
int index = word[j] - 'a'; // 计算孩子节点下标
if (!p[cur][index]) return 0; // 如果当前节点没有这个孩子,则没有这个单词,返回false
cur = p[cur][index]; // 遍历下一个节点
} else {
for (int k = 0; k < 26; k++) { // 此时是通配符,我们需要寻找出所有的可能
if (p[cur][k]) { // 找到当前节点存在的一个孩子
bool ans = search(p[cur][k], word, j + 1); // 以这个孩子为根节点去遍历剩下的部分
if (ans) return 1; // 说明如果通配符是字符k + ‘a’ 则可以匹配这个单词
}
}
return 0; // 所有可能的孩子都枚举完都没有找到一个合适的匹配,返回false
}
}
return cnt[cur]; // 所有的串都走完了,看当前节点是否是某个单词的结尾
}
bool search(string word) {
return search(0, word, 0); // 如果遇到 ‘.’ 需要递归处理
}
};
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary* obj = new WordDictionary();
* obj->addWord(word);
* bool param_2 = obj->search(word);
*/