forked from halfrost/LeetCode-Go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path718. Maximum Length of Repeated Subarray.go
86 lines (79 loc) · 1.62 KB
/
718. Maximum Length of Repeated Subarray.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package leetcode
const primeRK = 16777619
// 解法一 二分搜索 + Rabin-Karp
func findLength(A []int, B []int) int {
low, high := 0, min(len(A), len(B))
for low < high {
mid := (low + high + 1) >> 1
if hasRepeated(A, B, mid) {
low = mid
} else {
high = mid - 1
}
}
return low
}
func min(a int, b int) int {
if a > b {
return b
}
return a
}
func hashSlice(arr []int, length int) []int {
// hash 数组里面记录 arr 比 length 长出去部分的 hash 值
hash, pl, h := make([]int, len(arr)-length+1), 1, 0
for i := 0; i < length-1; i++ {
pl *= primeRK
}
for i, v := range arr {
h = h*primeRK + v
if i >= length-1 {
hash[i-length+1] = h
h -= pl * arr[i-length+1]
}
}
return hash
}
func hasSamePrefix(A, B []int, length int) bool {
for i := 0; i < length; i++ {
if A[i] != B[i] {
return false
}
}
return true
}
func hasRepeated(A, B []int, length int) bool {
hs := hashSlice(A, length)
hashToOffset := make(map[int][]int, len(hs))
for i, h := range hs {
hashToOffset[h] = append(hashToOffset[h], i)
}
for i, h := range hashSlice(B, length) {
if offsets, ok := hashToOffset[h]; ok {
for _, offset := range offsets {
if hasSamePrefix(A[offset:], B[i:], length) {
return true
}
}
}
}
return false
}
// 解法二 DP 动态规划
func findLength1(A []int, B []int) int {
res, dp := 0, make([][]int, len(A)+1)
for i := range dp {
dp[i] = make([]int, len(B)+1)
}
for i := len(A) - 1; i >= 0; i-- {
for j := len(B) - 1; j >= 0; j-- {
if A[i] == B[j] {
dp[i][j] = dp[i+1][j+1] + 1
if dp[i][j] > res {
res = dp[i][j]
}
}
}
}
return res
}