单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例 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,这是没办法的,数据量这么大,又要DFS,所以可以考虑到要添加一些信息进行约束避免很多无效的搜索,比如,当搜索到某个位置,我们可以判断下一个位置是否可以构成存在于words中的字符串,如果可以构成就继续搜索,不然就停止搜索,如何快速判断当前搜索的字符串是否存在于words呢?
这个就是字典树的任务了,先把所有的words构建成字典树,不断dfs的时候不断去字典树查询,就很丝滑的通过了。
字典树 is all you need.
AC代码
class Solution {
public:
int trie[100000][26] = {0};
int color[100000] = {0};
int k = 1;
void insert(string w){
int p = 0;
for(int i=0; i<w.length(); i++){
int c = w[i] - 'a';
if(!trie[p][c]){
trie[p][c] = k;
k++;
}
p = trie[p][c];
}
color[p]++;
}
vector<string>q;
int xx[4] = {0,0,-1,1};
int yy[4] = {-1,1,0,0};
bool vis[15][15] = {false};
bool count[100000] = {false};
void dfs(vector<vector<char>>& board, int x, int y, int p, string s)
{
int c = board[x][y] - 'a';
//字典树判断当前字符串是否存在于树中
if(!trie[p][c])return;
p = trie[p][c];
if(color[p]>0&&count[p]==false)
{
q.push_back(s);
//标记是否添加过,避免重复添加
count[p] = true;
}
for(int i=0;i<4;i++)
{
int x2 = x + xx[i];
int y2 = y + yy[i];
if(x2<0||x2>=board.size()||y2<0||y2>=board[0].size())continue;
if(vis[x2][y2])continue;
vis[x2][y2] = true;
dfs(board, x2, y2, p, s + board[x2][y2]);
vis[x2][y2] = false;
}
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words)
{
for(int i=0;i<words.size();i++)
insert(words[i]);
for(int i=0;i<board.size();i++)
{
for(int j=0;j<board[i].size();j++)
{
string s = "";
s += board[i][j];
vis[i][j] = true;
dfs(board, i, j, 0, s);
vis[i][j] = false;
}
}
return q;
}
};