Leetcode 212. 单词搜索 II 字典树优化dfs
Leetcode 212. 单词搜索 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 中的所有字符串互不相同
题解
首先将所有words插入字典树,这样在dfs搜索的时候就可以进行减枝。
指针版本:
class Solution {
public:
struct Node {
int id;
Node *son[26];
Node() {
id = -1;
for (int i = 0; i < 26; i ++ ) son[i] = NULL;
}
}*root;
unordered_set<int> ids;
vector<vector<char>> g;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void insert(string& word, int id) {
auto p = root;
for (auto c: word) {
int u = c - 'a';
if (!p->son[u]) p->son[u] = new Node();
p = p->son[u];
}
p->id = id;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
g = board;
root = new Node();
for (int i = 0; i < words.size(); i ++ ) insert(words[i], i);
for (int i = 0; i < g.size(); i ++ )
for (int j = 0; j < g[i].size(); j ++ ) {
int u = g[i][j] - 'a';
if (root->son[u])
dfs(i, j, root->son[u]);
}
vector<string> res;
for (auto id: ids) res.push_back(words[id]);
return res;
}
void dfs(int x, int y, Node* p) {
if (p->id != -1) ids.insert(p->id);
char t = g[x][y];
g[x][y] = '.';
for (int i = 0; i < 4; i ++ ) {
int a = x + dx[i], b = y + dy[i];
if (a >= 0 && a < g.size() && b >= 0 && b < g[0].size() && g[a][b] != '.') {
int u = g[a][b] - 'a';
if (p->son[u]) dfs(a, b, p->son[u]);
}
}
g[x][y] = t;
}
};
数组版本
class Solution {
public:
int son[100005][30], idx, id[100005], n, m;
vector<vector<char>> g;
unordered_set<int> ids;
int dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0};
void insert(string s, int i){
int p = 0;
for(char x : s){
int u = x - 'a';
if(!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
}
id[p] = i;
}
void dfs(int x, int y, int p){
if(id[p] != -1) ids.insert(id[p]);
char t = g[x][y];
g[x][y] = '.';
for(int i = 0; i < 4; i++){
int a = x + dx[i], b = y + dy[i];
if(a >= 0 && a < n && b >= 0 && b < m && g[a][b] != '.'){
int u = g[a][b] - 'a';
if(son[p][u]){
dfs(a, b, son[p][u]);
}
}
}
g[x][y] = t;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
memset(id, -1, sizeof(id));
for(int i = 0; i < words.size(); i++){
insert(words[i], i);
}
g = board;
n = g.size(), m = g[0].size();
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
int u = g[i][j] - 'a';
if(son[0][u])
dfs(i, j, son[0][u]);
}
}
vector<string> res;
for(int id : ids){
res.push_back(words[id]);
}
return res;
}
};