给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例:
输入:
words = ["oath","pea","eat","rain"]
and board =
[
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
输出: ["eat","oath"]
说明:
你可以假设所有输入都由小写字母 a-z
组成。
提示:
- 你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
- 如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。
class Solution {
class Trie{
public:
Trie *children[26]; //指向其子序列 从'a'到'z'
bool leaf; //该结点是否是叶子结点
int idx; //如果该节点是叶子结点, idx是该单词在vector中的序号
Trie()
{
this->leaf = false;
this->idx = 0;
fill_n(this->children, 26, nullptr);
}
};
public:
void insertWords(Trie *root, vector<string>& words, int idx)
{
int pos = 0, len = words[idx].size();
while(pos < len)
{
if(NULL == root->children[words[idx][pos] - 'a'])
root->children[words[idx][pos] - 'a'] = new Trie();
root = root->children[words[idx][pos++] - 'a'];
}
root->leaf = true;
root->idx = idx;
}
Trie * buildTrie(vector<string>& words)
{
Trie * root = new Trie();
for(int i = 0; i < words.size(); ++i)
insertWords(root, words, i);
return root;
}
void checkWords(vector<vector<char>>& board, int i, int j, int row, int col, Trie *root, vector<string> &res, vector<string>& words)
{
if(i <0 || j < 0 || i >= row || j >= col)
return;
if(board[i][j] == 'X')
return;
if(NULL == root->children[board[i][j] - 'a'])
return;
char temp = board[i][j];
if(root->children[temp - 'a']->leaf)
{
res.push_back(words[root->children [temp - 'a']->idx]);
root->children[temp - 'a']->leaf = false;
}
board[i][j] = 'X';
checkWords(board, i-1, j, row, col, root->children[temp-'a'], res, words);
checkWords(board, i+1, j, row, col, root->children[temp-'a'], res, words);
checkWords(board, i, j-1, row, col, root->children[temp-'a'], res, words);
checkWords(board, i, j+1, row, col, root->children[temp-'a'], res, words);
board[i][j] = temp;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words)
{
vector<string> res;
int row = board.size();
if(0==row)
return res;
int col = board[0].size();
if(0==col)
return res;
int wordCount = words.size();
if(0==wordCount)
return res;
Trie *root = buildTrie(words);
int i,j;
for(i =0 ; i<row; i++)
{
for(j=0; j<col; j++)
{
checkWords(board, i, j, row, col, root, res, words);
}
}
return res;
}
};