Reputation: 2082
Given two matrices A and B.
Is there efficient or more pythonic way to find if B is a Sub-Matrix
of A?
The code below is worked but I got a Time limit exceeded when the matrix is so big!
Note: The matrix data structure is represented as an array of strings.
[Input]
A=[
'7283455864',
'6731158619',
'8988242643',
'3830589324',
'2229505813',
'5633845374',
'6473530293',
'7053106601',
'0834282956',
'4607924137']
B=[
'9505',
'3845',
'3530']
[Code]
def gridSearch(G, P):
# Write your code here
n=len(G) # Matrix G row number
m=len(G[0]) # Matrix G col number
r=len(P) # Matrix P row number
c=len(P[0]) # Matrix P col number
found='NO'
for i in range(n-r+1):
for j in range(m-c+1):
start_row=i
end_row=i+r
start_col=j
end_col=j+c
sub=[]
if G[start_row][start_col]==P[0][0]:
sub=[x[start_col:end_col] for x in G[start_row:end_row] ]
if (sub==P):
found='YES'
#print(i,j)
return(found)
[Expected Output]
YES
Upvotes: 2
Views: 1308
Reputation: 3288
Rather than search on a letter by letter basis as you seem to be doing with your code, I would utilize the ability to search for strings within another string as follows:
def gridSearch(G, P):
g_sze = len(G)
p_sze = len(P)
p_ptr = 0
for g_ptr, g_row in enumerate(G):
if P[p_ptr] in g_row:
p_ptr += 1
if p_ptr == p_sze:
return True
else:
p_ptr = 0
if g_sze - g_ptr < p_sze-p_ptr:
return False
return False
The above code makes use of two efficiency approaches, first it searches the arrays by rows and secondly it stops searching rows when the ability to match the remaining rows of the smaller array is no longer possible
Given your second example, here is an approach which uses the string search approach and requires column alignment.
def gridSearch2(G, P):
g_sze = len(G)
p_sze = len(P)
candidates = []
# First scan for possible start postions
for row in range(g_sze - p_sze + 1):
idx = 0
while idx < g_sze - p_sze:
ptr = G[row].find(P[0], idx)
if ptr < 0:
break
candidates.append((row, ptr+idx))
idx = idx + ptr + 1
# test each possible start postion for matching follow on rows
while len(candidates) > 0:
row, idx = candidates.pop(0);
rslt = True
for pr in range(1, p_sze):
if G[row + pr].find(P[pr], idx) != idx:
rslt = False
break
if rslt:
return True
return False
Upvotes: 3