// improvement:
// 1) convert unordered_map to 26 bitmap (done)
// 2) for each step in dfs, we don't have search the word from beginning in trie,
// we can actually search from previous node. should be faster.
class Node {
public:
char v;
bool isWord;
vector<Node*> m;
//unordered_map<char, Node*> m;
Node(char _v, bool _isWord = false) {
v = _v;
isWord = _isWord;
m = vector<Node*>(26, nullptr);
}
};
class Trie {
public:
Node *root = new Node(0);
void build(vector<string>& words) {
for (auto& w : words)
add(w);
}
void add(const string& w) {
Node *cur = root;
for (auto c : w) {
if (cur->m[c-'a'] == nullptr)
cur->m[c-'a'] = new Node(c);
cur = cur->m[c-'a'];
}
cur->isWord = true;
}
int search(string &w) {
Node *cur = root;
for (auto c : w) {
if (cur->m[c-'a'] == nullptr)
return 0;
cur = cur->m[c-'a'];
}
return cur->isWord ? 2 : 1;
}
};
class Solution {
public:
int m, n;
unordered_set<string> res;
string path;
Trie trie;
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
m = board.size(); if (m == 0) return vector<string>();
n = board[0].size(); if (n == 0) return vector<string>();
trie.build(words);
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
path.push_back(board[i][j]);
dfs(board, i, j);
path.pop_back();
}
return vector<string>(res.begin(), res.end());
}
void dfs(vector<vector<char>>& board, int i, int j) {
static int dirs[] = { -1, 0, 1, 0, -1};
int state = trie.search(path);
if (state == 2)
res.insert(path);
else if (state == 0)
return;
char saved = board[i][j];
board[i][j] = ' ';
for (int k = 0; k < 4; k++) {
int ni = i + dirs[k];
int nj = j + dirs[k+1];
if (ni < 0 || ni >= m || nj < 0 || nj >= n || board[ni][nj] == ' ')
continue;
path.push_back(board[ni][nj]);
dfs(board, ni, nj);
path.pop_back();
}
board[i][j] = saved;
}
};