题目地址:
https://leetcode.com/problems/word-search-ii/
给定一个二维字符矩阵,再给定若干单词,问是否存在矩阵中的某条路径使得这个路径上字符组成的单词恰好就是那几个单词之一,要求返回所有满足条件的单词。路径不允许走到相同格子上。
思路是DFS + Trie。想到DFS是自然的,由于要搜索多个字符串,为了避免多次重复搜索,我们可以在DFS的时候带着Trie节点一起搜,相当于同时在矩阵和Trie里搜索,当同时搜到某个单词的时候,就可以加入结果了。代码如下:
class Solution {
public:
struct Node {
Node *son[26];
bool is_word;
} * root;
int d[5] = {-1, 0, 1, 0, -1};
void insert(string &s) {
auto p = root;
for (auto &c : s) {
int idx = c - 'a';
if (!p->son[idx]) p->son[idx] = new Node();
p = p->son[idx];
}
p->is_word = true;
}
vector<string> findWords(vector<vector<char>> &g, vector<string> &ws) {
root = new Node();
for (auto &s : ws) insert(s);
unordered_set<string> res;
for (int i = 0; i < g.size(); i++)
for (int j = 0; j < g[0].size(); j++) {
string s;
auto p = root;
dfs(i, j, p, s, res, g);
}
return vector<string>(res.begin(), res.end());
}
// 这里的cur实际上是board[x][y]这条Trie边的上面的节点
void dfs(int x, int y, Node *p, string &s, unordered_set<string> &res,
vector<vector<char>> &g) {
char ch = g[x][y];
if (!p->son[ch - 'a']) return;
p = p->son[ch - 'a'];
s += ch;
if (p->is_word) res.insert(s);
// 标记为访问过
g[x][y] = 0;
for (int i = 0; i < 4; i++) {
int nx = x + d[i], ny = y + d[i + 1];
if (0 <= nx && nx < g.size() && 0 <= ny && ny < g[0].size() &&
g[nx][ny]) {
dfs(nx, ny, p, s, res, g);
}
}
g[x][y] = ch;
s.pop_back();
}
};
时间复杂度与具体情况有关,比较难分析。空间复杂度 O ( m n + s ) O(mn+s) O(mn+s)( s s s为words里单词总长度)。