Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
For example,
Given words = ["oath","pea","eat","rain"] and board =
[
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
Return ["eat","oath"].
Note:
You may assume that all inputs are consist of lowercase letters a-z.
/*
* @lc app=leetcode id=212 lang=cpp
*
* [212] Word Search II
*
* https://leetcode.com/problems/word-search-ii/description/
*
* algorithms
* Hard (29.77%)
* Likes: 1405
* Dislikes: 78
* Total Accepted: 132.7K
* Total Submissions: 440.4K
* Testcase Example: '[["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]]\n["oath","pea","eat","rain"]'
*
* Given a 2D board and a list of words from the dictionary, find all words in
* the board.
*
* Each word must be constructed from letters of sequentially adjacent cell,
* where "adjacent" cells are those horizontally or vertically neighboring. The
* same letter cell may not be used more than once in a word.
*
*
*
* Example:
*
*
* Input:
* board = [
* ['o','a','a','n'],
* ['e','t','a','e'],
* ['i','h','k','r'],
* ['i','f','l','v']
* ]
* words = ["oath","pea","eat","rain"]
*
* Output: ["eat","oath"]
*
*
*
*
* Note:
*
*
* All inputs are consist of lowercase letters a-z.
* The values of words are distinct.
*
*
*/
class Solution
{
public:
class TrieNode
{
public:
vector<TrieNode *> children;
string word;
TrieNode(): children(26){}
};
TrieNode *build(vector<string> &words)
{
TrieNode *root = new TrieNode(), *node;
for (const auto &word : words)
{
node = root;
for (const auto c : word)
{
const int idx = c - 'a';
if (node->children[idx] == nullptr)
node->children[idx] = new TrieNode();
node = node->children[idx];
}
node->word = word;
}
return root;
}
void dfs(vector<vector<char>> &board, int i, int j, vector<vector<int>> &dirs, TrieNode *node, vector<string> &res) {
const int idx = board[i][j] - 'a';
if (idx >= 26 || node->children[idx] == nullptr) return;
node = node->children[idx];
if (node->word != "") {
res.push_back(node->word);
node->word = "";
}
for (const auto &dir : dirs) {
int x = i + dir[0], y = j + dir[1];
if (x >= 0 && x < board.size() && y >= 0 && y < board[0].size()) {
const char tmp = board[i][j];
board[i][j] = 'z' + 1;
dfs(board, x, y, dirs, node, res);
board[i][j] = tmp;
}
}
}
vector<string> findWords(vector<vector<char>> &board, vector<string> &words)
{
vector<string> res;
TrieNode *root = build(words);
vector<vector<int>> dirs = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
for (int i = 0; i < board.size(); ++i) {
for (int j = 0; j < board[0].size(); ++j) {
dfs(board, i, j, dirs, root, res);
}
}
return res;
}
};
class Solution {
public TrieNode buildTrie(String[] words) {
TrieNode root = new TrieNode(), node;
for (String word : words) {
node = root;
for (int i = 0; i < word.length(); i++) {
int index = word.charAt(i) - 'a';
if (node.children[index] == null) {
node.children[index] = new TrieNode();
}
node = node.children[index];
}
node.word = word;
}
return root;
}
class TrieNode {
TrieNode[] children = new TrieNode[26];
String word = null;
}
static final int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
private void dfs(char[][] board, int i, int j, TrieNode node, List<String> res) {
int index = board[i][j] - 'a';
if (index >= 26 || node.children[index] == null) {
return;
} else {
node = node.children[index];
if (node.word != null) {
res.add(node.word);
node.word = null;
}
}
for (int[] dir : dirs) {
int x = i + dir[0], y = j + dir[1];
if (x >= 0 && x < board.length && y >= 0 && y < board[0].length) {
board[i][j] ^= 256;
dfs(board, x, y, node, res);
board[i][j] ^= 256;
}
}
}
public List<String> findWords(char[][] board, String[] words) {
List<String> res = new ArrayList<>();
TrieNode root = buildTrie(words);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
dfs(board, i, j, root, res);
}
}
return res;
}
}