Description

Given an m x n board of characters and a list of strings words, return all words on the board.

Each word must be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

Intuition

The Trie data structure allows for efficient prefix-based searching, reducing unnecessary traversals. Backtracking explores all possible paths on the board to match words.

Approach

  1. Construct a Trie: Build a Trie from the given list of words, where each node represents a character and stores the full word at the end of a valid path.
  2. Backtracking:
    • For each cell in the board, check if it starts a word in the Trie.
    • Recursively explore its neighbors while marking visited cells to avoid revisits.
    • Add matched words to the result set and terminate paths that cannot yield further valid words.

Code

class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        n, m = len(board), len(board[0])
        directions = [[0,1],[0,-1],[1,0],[-1,0]]
        trie = {}
        for word in words:
            pointer = trie
            for char in word:
                if char not in pointer:
                    pointer[char] = {}
                pointer = pointer[char]
            pointer['$'] = word
 
        def backtrack(trie, used, i, j):
            if '$' in trie:
                ans.add(trie['$'])
                if len(trie) == 1:
                    return
            for dx, dy in directions:
                x, y = i + dx, j + dy
                if (x, y) in used or not (0 <= x < n and 0 <= y < m) or board[x][y] not in trie:
                    continue
                used.add((x, y))
                backtrack(trie[board[x][y]], used, x, y)
                used.remove((x, y))
 
        ans = set()
        for i in range(n):
            for j in range(m):
                # All words are found
                if len(ans) == len(words):
                    break
                if not board[i][j] in trie:
                    continue
                backtrack(trie[board[i][j]], {(i, j)}, i, j)
 
        return list(ans)