class Trie:
def __init__(self):
self.root = dict()
def insert(self, word):
root = self.root
for c in word + '&':
if c not in root:
root[c] = dict()
root = root[c]
@lru_cache(None)
def search(self, word):
root = self.root
for c in word:
if c not in root:
return False
root = root[c]
return True if '&' in root else False
@lru_cache(None)
def startwith(self, prefix):
root = self.root
for c in prefix:
if c not in root:
return False
root = root[c]
return True
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
n, m = len(board), len(board[0])
trie = Trie()
for w in words:
trie.insert(w)
res = set()
def dfs(i, j, prefix):
if not 0 <= i < n or not 0 <= j < m:
return False
new_prefix = prefix + board[i][j]
if not trie.startwith(new_prefix):
return False
if trie.search(new_prefix):
res.add(new_prefix)
tmp, board[i][j] = board[i][j], '/'
t = dfs(i + 1, j, new_prefix) or dfs(i - 1, j, new_prefix) or dfs(i, j + 1, new_prefix) or dfs(i, j - 1, new_prefix)
board[i][j] = tmp
return t
for i in range(n):
for j in range(m):
dfs(i, j, '')
return list(res)