Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
Example:
Input: board = [ ['o','a','a','n'], ['e','t','a','e'], ['i','h','k','r'], ['i','f','l','v'] ] words =["oath","pea","eat","rain"]
Output:["eat","oath"]
/* 一个很复杂的大问题: 给定矩形字符阵
* 只能水平方向或竖直方向移动 求在字典中能搜出来的
* 显然可以对字典中每个字符走一趟dfs
* 但是: 字典中某些单词如果有共同前缀
* 在矩阵中搜索向trie上的非空节点(相当于在trie上深搜)
* */
struct TrieNode{
TrieNode* child[26];
bool isEnd;
TrieNode():isEnd(false){
for(int i=0;i<26;i++){
child[i] = NULL;
}
}
};
class Trie{
public:
TrieNode *root;
Trie(vector<string> &dicts){
root = new TrieNode();
for(string &s : dicts){
insert(s);
}
}
void delNode(TrieNode *root){
for(auto &child : root->child){
if(child) delNode(child);
}
delete(root);
}
~Trie(){
delNode(root);
}
void insert(string &words){
auto tmp = root;
for(char &c : words){
int id = c-'a';
if(tmp->child[id]==NULL){
TrieNode *node = new TrieNode();
tmp->child[id] = node;
}
tmp = tmp->child[id];
}
tmp->isEnd = true;
}
bool find(string &words){
auto tmp=root;
for(char &c:words){
int id = c-'a';
if(tmp->child[id]==NULL) return false;
else tmp = tmp->child[id];
}
return tmp->isEnd;
}
};
class Solution {
public:
set<string> found;
int row, col;
int dx[4]={0, 0, 1, -1};
int dy[4]={1,-1, 0, 0};
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
// 每个位置对trie树dfs 递归搜索并记录已经得到的结果
row=board.size(), col=board[0].size();
Trie *trie = new Trie(words);
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
dfs(board, "", trie->root, i, j);
}
}
delete(trie);
vector<string> ret;
for(auto &s:found) ret.push_back(s);
return ret;
}
// 注意root指向当前节点的前一个(第一次dfs时 root指向树的根节点 执行一次root->child才到当前节点)
void dfs(vector<vector<char>>& board, string word, TrieNode *root, int x, int y){
// 当前位置四个方向没有越界 没有拐回到遍历过的路径上 并且在字典树的路径上存在的点继续dfs
if(x<0 || x==row || y<0 || y==col || board[x][y]=='#') return;
root = root->child[board[x][y]-'a'];
if(!root) return;
word.push_back(board[x][y]);
if(root->isEnd) found.insert(word);
char tmp = board[x][y];
board[x][y]='#';
for(int i=0;i<4;i++){
dfs(board, word, root, x+dx[i], y+dy[i]);
}
board[x][y]=tmp;
}
};