输入:
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 组成。
提示:
你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
解题思路
DFS + Trie树
索引超越边界, 剪枝
当前前缀不在树中, 剪枝
搜索到单词就添加到结果中, 但不能停止, 因为可能是另一个单词的前缀.
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)