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
中的所有字符串互不相同
字典树/前缀树,模板题。最初版本见题号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; }