You are given an m x n
matrix grid
consisting of characters and a string pattern
.
A horizontal substring is a contiguous sequence of characters read from left to right. If the end of a row is reached before the substring is complete, it wraps to the first column of the next row and continues as needed. You do not wrap from the bottom row back to the top.
A vertical substring is a contiguous sequence of characters read from top to bottom. If the bottom of a column is reached before the substring is complete, it wraps to the first row of the next column and continues as needed. You do not wrap from the last column back to the first.
Count the number of cells in the matrix that satisfy the following condition:
pattern
.Return the count of these cells.
For example:
grid = [['a','a','c','c'],['b','b','b','c'],['a','a','b','a'],['c','a','a','c'],['a','a','b','a']], pattern = 'abaca'
Output: 1
Explanation: The pattern 'abaca'
appears once as a horizontal substring and once as a vertical substring, intersecting at one cell.
grid = [['c','a','a','a'],['a','a','b','a'],['b','b','a','a'],['a','a','b','a']], pattern = 'aba'
Output: 4
Explanation: The cells are all part of at least one horizontal and one vertical substring matching the pattern 'aba'
.
grid = [['a']], pattern = 'a'
Output: 1
pattern
exists as a horizontal substring (with wrapping). If a match is found, mark all cells in the substring as part of a horizontal match.pattern
exists as a vertical substring (with wrapping). If a match is found, mark all cells in the substring as part of a vertical match.Code (Python):
def count_intersections_brute_force(grid, pattern):
m, n = len(grid), len(grid[0])
len_pattern = len(pattern)
horizontal_matches = set()
vertical_matches = set()
# Helper functions to check for horizontal and vertical matches
def check_horizontal(row, col):
substring = ""
for i in range(len_pattern):
substring += grid[row][(col + i) % n]
return substring == pattern
def check_vertical(row, col):
substring = ""
for i in range(len_pattern):
substring += grid[(row + i) % m][col]
return substring == pattern
# Find horizontal matches
for r in range(m):
for c in range(n):
if check_horizontal(r, c):
for i in range(len_pattern):
horizontal_matches.add((r, (c + i) % n))
# Find vertical matches
for r in range(m):
for c in range(n):
if check_vertical(r, c):
for i in range(len_pattern):
vertical_matches.add(((r + i) % m, c))
# Count cells in both horizontal and vertical matches
count = 0
for r in range(m):
for c in range(n):
if (r, c) in horizontal_matches and (r, c) in vertical_matches:
count += 1
return count
Time Complexity: O(m * n * len(pattern)), where m
is the number of rows, n
is the number of columns, and len(pattern)
is the length of the pattern string. We iterate over all m*n
cells, and for each cell, we potentially iterate len(pattern)
times to check for both horizontal and vertical matches.
Space Complexity: O(m * n) in the worst case, to store the horizontal_matches
and vertical_matches
sets, where each set could contain all cells of the grid.
The brute-force solution is inefficient because it repeatedly constructs substrings. An optimized approach can be outlined as follows:
horizontal_match
of size m x n
. horizontal_match[i][j]
will be True
if a horizontal substring matching pattern
starts at grid[i][j]
. This can be precomputed by checking every possible starting position. The string comparison can be improved using rolling hash to reduce time complexity of string comparison from O(len(pattern)) to O(1). Alternatively, the naive string comparison doesn't hurt the overall time complexity since it is dominated by the iteration over cells.vertical_match
of size m x n
. vertical_match[i][j]
will be True
if a vertical substring matching pattern
starts at grid[i][j]
. Precompute as above.grid[i][j]
, check if it's part of a horizontal substring AND a vertical substring equal to the pattern
. If so, increment the count.To determine if a cell grid[i][j]
is part of a horizontal substring, check if there exists k
such that grid[i][(j - k + n) % n]
exists and horizontal_match[i][(j - k + n) % n]
is true and 0 <= k < len(pattern).
Do the same for the vertical substring.
Code (Python):
def count_intersections_optimized(grid, pattern):
m, n = len(grid), len(grid[0])
len_pattern = len(pattern)
horizontal_match = [[False] * n for _ in range(m)]
vertical_match = [[False] * m for _ in range(n)]
# Find horizontal matches
for r in range(m):
for c in range(n):
if c + len_pattern <= n:
substring = "".join(grid[r][c + i] for i in range(len_pattern))
if substring == pattern:
horizontal_match[r][c] = True
# Find vertical matches
for c in range(n):
for r in range(m):
if r + len_pattern <= m:
substring = "".join(grid[r + i][c] for i in range(len_pattern))
if substring == pattern:
vertical_match[c][r] = True
# Count intersections
count = 0
for r in range(m):
for c in range(n):
is_horizontal = False
for k in range(len_pattern):
prev_c = (c - k + n) % n
if prev_c + len_pattern <= n and horizontal_match[r][prev_c]:
is_horizontal = True
break
is_vertical = False
for k in range(len_pattern):
prev_r = (r - k + m) % m
if prev_r + len_pattern <= m and vertical_match[c][prev_r]:
is_vertical = True
break
if is_horizontal and is_vertical:
count += 1
return count
Time Complexity: O(m * n * len(pattern)) if using naive string comparision for horizontal and vertical matching. O(m * n) if using rolling hash for horizontal and vertical matching.
Space Complexity: O(m * n) to store the horizontal_match
and vertical_match
boolean arrays.
m = 0
or n = 0
. Return 0.len(pattern) = 0
. Return 0 (no possible matches).