这道题是DFS+前缀树,是一道标准的模板题
这里面的Tire类的定义写的方法与之前的 208 略有不同,但基本上一样。只是单独定义了一下TireNode节点类。
//定义节点,类/结构体
class TireNode {
public:
TireNode(){
}
bool isEnd = false;
vector<TireNode*> next = vector<TireNode*> (26, nullptr);
};
class Tire {
public:
TireNode* root = new TireNode(); // 建立根节点
Tire() {
}
void insert(string s) {
TireNode* node = root;
for(char ch : s) {
if(node->next[ch-'a'] == nullptr) {
node->next[ch-'a'] = new TireNode();
}
node = node->next[ch-'a'];
}
node->isEnd = true;
}
bool search(string s) {
TireNode* node = root;
for(char ch : s) {
node = node->next[ch-'a'];
if(node == nullptr) {
return false;
}
}
return node->isEnd;
}
bool isPrefix(string s) {
TireNode* node = root;
for(char ch : s) {
node = node->next[ch-'a'];
if(node == nullptr) {
return false;
}
}
return true;
}
};
class Solution {
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
//第一步,用字典树来存储字典列表中的所有字符串
Tire tire;
for(string s : words) {
tire.insert(s);
}
set<string> ans; //定义set作为装结果的容器,防止重复
//对二维网格的每一个点都进行四个方向的深度优先遍历
for(int i = 0; i < board.size(); i++) {
for(int j = 0; j < board[i].size(); j++) {
string cur = "";
cur += board[i][j];
board[i][j] -= 26;
DFS(board, tire, ans, cur, i, j);
board[i][j] += 26;
}
}
vector<string> res;
for(string s : ans) {
res.push_back(s);
}
return res;
}
void DFS(vector<vector<char>>& board, Tire& tire, set<string>& res, string& cur, int x, int y) {
if(!tire.isPrefix(cur)) { //当前的字符串不在前缀树中,直接返回
return;
}
if(tire.search(cur)) { //当前字符串是前缀树中的一个单词,直接加入结果中
res.insert(cur);
}
//当前字符串是前缀树中的一个前缀,依次向4个方向进行DFS的探索
if(x-1 >= 0 && board[x-1][y] >= 'a') {
cur += board[x-1][y];
board[x-1][y] -= 26; //将加入字符串的那个字符减去'a'防止这次再访问
DFS(board, tire, res, cur, x-1, y); //继续递归
board[x-1][y] += 26; //这次递归完返回之后要将字符恢复,用于下次查找
cur = cur.substr(0, cur.size()-1); //去掉最后一个字符
}
if(y-1 >= 0 && board[x][y-1] >= 'a') {
cur += board[x][y-1];
board[x][y-1] -= 26; //将加入字符串的那个字符减去'a'防止这次再访问
DFS(board, tire, res, cur, x, y-1); //继续递归
board[x][y-1] += 26; //这次递归完返回之后要将字符恢复,用于下次查找
cur = cur.substr(0, cur.size()-1); //去掉最后一个字符
}
if(x+1 < board.size() && board[x+1][y] >= 'a') {
cur += board[x+1][y];
board[x+1][y] -= 26; //将加入字符串的那个字符减去'a'防止这次再访问
DFS(board, tire, res, cur, x+1, y); //继续递归
board[x+1][y] += 26; //这次递归完返回之后要将字符恢复,用于下次查找
cur = cur.substr(0, cur.size()-1); //去掉最后一个字符
}
if(y+1 < board[0].size() && board[x][y+1] >= 'a') { //bug:x,y轴方向不是任意的,需要和主函数中for循环的i,j的范围对应,因此x是纵轴
cur += board[x][y+1];
board[x][y+1] -= 26; //将加入字符串的那个字符减去'a'防止这次再访问
DFS(board, tire, res, cur, x, y+1); //继续递归
board[x][y+1] += 26; //这次递归完返回之后要将字符恢复,用于下次查找
cur = cur.substr(0, cur.size()-1); //去掉最后一个字符
}
}
};