Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to count number of words we can generate from matrix of letters in Python
Suppose we have a 4 x 4 board of letters and a list of words, we have to find the largest number of words that can be generated in the board by a sequence of adjacent letters, using one cell at most once per word (but we can reuse cells for other words). We can go up, down, left, right, or diagonal direction.
Problem Example
If the input is like ?
| m | b | f | d |
| x | a | y | a |
| t | z | t | r |
| s | q | q | q |
words = ["bat", "far", "mat"], then the output will be 3, as we can generate mat [0,1] ? [1,1] ? [2,0], bat [0,2] ? [1,1] ? [2,2], and far [0,2] ? [1,3] ? [2,3].
Algorithm Approach
To solve this, we will follow these steps ?
- Build a trie (prefix tree) from all words for efficient word searching
- Use depth-first search (DFS) with backtracking to explore all possible paths
- Mark visited cells temporarily during each word search
- Count words found and remove them from the trie to avoid duplicates
Implementation
class Solution:
def solve(self, matrix, words):
rows = len(matrix)
cols = len(matrix[0])
# Build trie from words
trie = {}
for word in words:
current = trie
for char in word:
if char not in current:
current[char] = {}
current = current[char]
current["*"] = True # Mark end of word
found_count = 0
def dfs(x, y, trie_node):
nonlocal found_count
# If we found a complete word
if "*" in trie_node:
del trie_node["*"] # Remove to avoid counting again
found_count += 1
# Save current cell value and mark as visited
temp = matrix[x][y]
matrix[x][y] = "#"
# Explore all 8 directions (including diagonals)
for i in range(x-1, x+2):
for j in range(y-1, y+2):
if (0 <= i < rows and 0 <= j < cols and
matrix[i][j] != "#" and matrix[i][j] in trie_node):
dfs(i, j, trie_node[matrix[i][j]])
# Restore cell value (backtrack)
matrix[x][y] = temp
# Try starting from each cell
for i in range(rows):
for j in range(cols):
if matrix[i][j] in trie:
dfs(i, j, trie[matrix[i][j]])
return found_count
# Test the solution
ob = Solution()
matrix = [
["m", "b", "f", "d"],
["x", "a", "y", "a"],
["t", "z", "t", "r"],
["s", "q", "q", "q"]
]
words = ["bat", "far", "mat"]
result = ob.solve(matrix, words)
print(f"Number of words found: {result}")
Output
Number of words found: 3
How It Works
The algorithm uses a trie data structure to efficiently store and search for words. Here's the process ?
- Trie Construction: All words are inserted into a trie for fast prefix matching
- DFS Search: For each cell, we explore all 8 adjacent directions recursively
- Backtracking: Cells are temporarily marked as visited ("#") and restored after exploration
- Word Detection: When we reach a trie node with "*", we've found a complete word
Key Points
- Each cell can be used multiple times across different words
- Within a single word search, each cell can only be used once
- Movement is allowed in all 8 directions (horizontal, vertical, diagonal)
- The trie prevents counting the same word multiple times
Conclusion
This solution combines trie data structure with DFS backtracking to efficiently find all possible words in a letter matrix. The approach ensures optimal word searching while preventing duplicate counting through trie manipulation.
