一、题目
二、题解
这个题目是让我们在一个字符矩阵中检索是否存在目标单词,存在就将目标单词枚举返回,对于单词的匹配可以使用前缀树来存储,然后我们枚举矩阵的所有可能的单词,判断这个单词是否是题目中所给的通过Trie树的search查询即可,枚举时需要通过dfs枚举每一个位置开头的单词,如果在dfs过程中发生他不是单词s的前缀,则进行剪枝
(关于Trie树的操作可以在主页搜索Trie)
class Solution {
public:
int son[9000][26], idx, cnt[9000], n, nn; // son数组存储trie树, idx用于申请节点(可以发布的查看211题的题解关于Trie树) cnt当前结束是否有单词, n表示行nn表示列
vector<string> ans; // 结果集合
string path; // 记录dfs过程中的单词
vector<vector<char>> m; // 将参数board变为全局m
bool check[9000][9000]; // check数组用于遍历过程中判断该字符是否被选择过
Solution() {
idx = 0;
memset(son, 0, sizeof(son));
memset(cnt, 0, sizeof(cnt));
}
void insert(vector<string>& words) { // Trie树插入操作
for (auto word : words) {
int p = 0;
for (auto x : word) {
int child = x - 'a';
if (!son[p][child]) son[p][child] = ++idx;
p = son[p][child];
}
cnt[p] ++;
}
}
bool search(string path) { // 查询path是否在Trie中
int p = 0;
for (auto x : path) {
int index = x - 'a';
if (!son[p][index]) return 0;
p = son[p][index];
}
int ans = cnt[p];
cnt[p] = cnt[p] == 0 ? 0 : cnt[p] - 1;
return ans;
}
bool startsWith(string prefix) { // 查询prefix是否是前缀
int p = 0;
for (auto x : prefix) {
int child = x - 'a';
if (!son[p][child]) return 0;
p = son[p][child];
}
return 1;
}
void dfs(int i, int j) {
if(search(path)) {
ans.push_back(path);
}
// 如果当前path不是前缀进行剪枝
if (!startsWith(path)) return;
// dfs上下左右
if (i - 1 >= 0 && !check[i - 1][j]) {
path += m[i-1][j];
check[i - 1][j] = true;
dfs(i - 1, j);
check[i - 1][j] = false;
path.pop_back();
}
if (i + 1 < n && !check[i + 1][j]) {
path += m[i + 1][j];
check[i + 1][j] = true;
dfs(i + 1, j);
check[i + 1][j] = false;
path.pop_back();
}
if (j + 1 < nn && !check[i][j + 1] ) {
path += m[i][j + 1];
check[i][j + 1] = true;
dfs(i, j + 1);
check[i][j + 1] = false;
path.pop_back();
}
if (j - 1 >= 0 && !check[i][j - 1] ) {
path += m[i][j - 1];
check[i][j - 1] = true;
dfs(i, j - 1);
check[i][j - 1] = false;
path.pop_back();
}
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
insert(words); // 将所有words插入Trie树
m = board;
n = m.size(), nn = m[0].size();
for (int i = 0; i < m.size(); i++) { // dfs每一个元素开头的单词
for (int j = 0; j < m[i].size(); j++) {
path += m[i][j];
check[i][j] = true;
dfs(i, j);
check[i][j] = false;
path.pop_back();
}
}
return ans;
}
};