718. Maximum Length of Repeated Subarray
Given two integer arrays nums1 and nums2, return the maximum length of a subarray that appears in both arrays.
def findLength(self, A, B):
memo = [[0] * (len(B) + 1) for _ in range(len(A) + 1)]
for i in range(len(A) - 1, -1, -1):
for j in range(len(B) - 1, -1, -1):
if A[i] == B[j]:
memo[i][j] = memo[i + 1][j + 1] + 1
return max(max(row) for row in memo)
Rolling hash
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
m, n = len(nums1), len(nums2)
BASE, MOD = 101, 1_000_000_000_001
hash1, hash2, POW = [0] * (m + 1), [0] * (n + 1), [1] * (max(m, n) + 1)
for i in range(max(m, n)): POW[i + 1] = POW[i] * BASE % MOD # Compute POW of BASE
for i in range(m): hash1[i + 1] = (hash1[i] * BASE + nums1[i]) % MOD # Compute hashing values of nums1
for i in range(n): hash2[i + 1] = (hash2[i] * BASE + nums2[i]) % MOD # Compute hashing values of nums2
def getHash(h, left, right): # 0-based indexing, right inclusive
return (h[right + 1] - h[left] * POW[right - left + 1] % MOD + MOD) % MOD
def foundSubArray(size):
seen = defaultdict(list)
for i in range(m - size + 1):
h = getHash(hash1, i, i + size - 1)
seen[h].append(i)
for i in range(n - size + 1):
h = getHash(hash2, i, i + size - 1)
if h in seen:
for j in seen[h]: # Double check - This rarely happens when collision occurs -> No change in time complexity
if nums1[j:j + size] == nums2[i:i + size]:
return True
return False
left, right, ans = 1, min(m, n), 0
while left <= right:
mid = (left + right) // 2
if foundSubArray(mid):
ans = mid # Update answer
left = mid + 1 # Try to expand size
else:
right = mid - 1 # Try to shrink size
return ans