单词搜索 II
给定一个 m x n
二维字符网格 board
和一个单词(字符串)列表 words
, 返回所有二维网格上的单词 。
单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例 1:
输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出:["eat","oath"]
示例 2:
输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 12
board[i][j]
是一个小写英文字母1 <= words.length <= 3 * 104
1 <= words[i].length <= 10
words[i]
由小写英文字母组成words
中的所有字符串互不相同
代码:
//dfs回溯+tire树剪枝
class Solution {
public:
int son[100010][26]={0},cent[100010]={0},idx=0;
//四个搜索方向
int dp[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n, m;
vector<string> res;
//构建字典树
void insert(string word) {
int p=0;
for(auto i:word){
int u=i-'a';
if(son[p][u]==0) son[p][u]=++idx;
p=son[p][u];
}
cent[p]++;
}
void dfs(vector<vector<char>>& board, int i, int j, string tmp,int id) {
if (i < 0 || j < 0 || i >= n || j >= m) return;
char c = board[i][j];
int u = c - 'a';
//是否用过则剪枝
if(c == '*' || son[id][u]==0) {
return;
}
id=son[id][u];
//是单词放到res中,并从字典树剔除
if(cent[id]>=1) {
res.push_back(tmp+c);
cent[id]= 0;
}
board[i][j] = '*';//标记已经访问过
//上、下、左、右四个方向遍历
for(int k =0; k<4; k++)
dfs(board, i+dp[k][0], j+dp[k][1], tmp + c,id);
board[i][j] = c; //回溯
return;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
n = board.size(), m = board[0].size();
for(auto z:words)
insert(z);
for (int i = 0; i < n; i++) //从每个起点开始寻找,是否有满足的单词
for (int j = 0; j < m; j++)
dfs(board, i, j, "",0);
return res;
}
};