https://leetcode.com/problems/maximum-length-of-repeated-subarray/
注意,这道题和1143. Longest Common Subsequence要区分开,这道题是subarray即连续区间,LCS题为子序列,可以不连续。
Given two integer arrays A
and B
, return the maximum length of an subarray that appears in both arrays.
Example 1:
Input:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
Output: 3
Explanation:
The repeated subarray with maximum length is [3, 2, 1].
Note:
- 1 <= len(A), len(B) <= 1000
- 0 <= A[i], B[i] < 100
- DP - 见代码1
- 字符串哈希算法 - 见代码2
dp[i][j]
数组表示 A[i...n] 和 B[j...m] 的最长公共连续subarray的元素个数(n, m为A, B长度)。
class Solution(object):
def findLength(self, A, B):
"""
:type A: List[int]
:type B: List[int]
:rtype: int
"""
ans, n1, n2 = 0, len(A), len(B)
dp = [(n2 + 1) * [0] for _ in range(n1 + 1)]
for i in range(n1-1, -1, -1):
for j in range(n2-1, -1, -1):
if A[i] == B[j]:
dp[i][j] = 1 + dp[i+1][j+1]
if dp[i][j] > ans:
ans = dp[i][j]
return ans
对比我写的两道题的代码,区别在于处理subsequence时,当两个字符/数字不相同时,DP数组也是可以取值的,即dp[i][j] = max(dp[i+1][j], dp[i][j+1])
, 表示当前位置的LCS数量,为字符串s1[i+1~]与s2[j~] or s1[i~]与s2[j+1~]的LCS最大值。
但是,如果是处理subarray,因为我们要求该位置的字符/数字必须与后一位相同,也就是要连续,假如A[i] != B[j],那么dp[i][j] = 0
,表示当把A[i], B[j]考虑在内,A[in] 与 B[jm] (包含i, j位)是没有共同的连续子区间。
- 思路:字符串哈希算法。先对每个区间对应成n个数,转化为P进制,存到HashSet。这样匹配某一段区间时就是O(1)的复杂度。
class Solution {
static long[] ha, hb, p;
static int P = 131;
static int n, m;
static long get(long[] h, int l, int r) {
return h[r] - h[l - 1] * p[r - l + 1];
}
public int findLength(int[] A, int[] B) {
n = A.length; m = B.length;
ha = new long[n + 1];
hb = new long[m + 1];
p = new long[n + 1];
for (int i = 1; i <= n; i++) ha[i] = ha[i - 1] * P + A[i - 1];
for (int i = 1; i <= m; i++) hb[i] = hb[i - 1] * P + B[i - 1];
p[0] = 1;
for (int i = 1; i <= n; i++) p[i] = p[i - 1] * P;
int l = 0, r = n;
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
public boolean check(int mid) {
Set<Long> S = new HashSet<>();
for (int i = mid; i <= n; i++) S.add(get(ha, i - mid + 1, i));
for (int i = mid; i <= n; i++)
if (S.contains(get(hb, i - mid + 1, i)))
return true;
return false;
}
}