给定一个 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
中的所有字符串互不相同
字典树/前缀树,模板题。最初版本见题号208,实现字典树。进阶如题号472,字典树+dfs记忆化搜索这类。
class Solution {
public:
struct Trie
{
Trie* child[26];
string word = "";
Trie() {
for (int i = 0; i < 26; i++)
child[i] = nullptr;
}
};
vector<string> ans;
void dfs(vector<vector<char>>& board,Trie* t,int i,int j)
{
char c=board[i][j];
if(c=='*'||t->child[c-'a']==nullptr) return;
t=t->child[c-'a'];
if(t->word!="")
{
ans.push_back(t->word);
t->word="";
}
board[i][j]='*';
if(i+1<board.size())dfs(board,t,i+1,j);
if(i-1>=0)dfs(board,t,i-1,j);
if(j+1<board[i].size())dfs(board,t,i,j+1);
if(j-1>=0)dfs(board,t,i,j-1);
board[i][j]=c;
return;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
Trie* t=new Trie();
for(int i=0;i<words.size();i++)
{
Trie* cur=t;
for(int j=0;j<words[i].size();j++)
{
if(cur->child[words[i][j]-'a']==nullptr)
{
cur->child[words[i][j]-'a']=new Trie();
}
cur=cur->child[words[i][j]-'a'];
}
cur->word=words[i];
}
for(int i=0;i<board.size();i++)
{
for(int j=0;j<board[i].size();j++)
{
dfs(board,t,i,j);
}
}
return ans;
}
};
前缀树模板:
一次建树,多次查询
class Trie {
private:
bool isEnd;
Trie* next[26];
public:
//方法在下面实现
};
void insert(string word) {
Trie* node = this;
for (char c : word) {
if (node->next[c-'a'] == NULL) {
node->next[c-'a'] = new Trie();
}
node = node->next[c-'a'];
}
node->isEnd = true;
}
bool search(string word) {
Trie* node = this;
for (char c : word) {
node = node->next[c - 'a'];
if (node == NULL) {
return false;
}
}
return node->isEnd;
}