最长公共子序列可延生出两个题目
输入:
[0,1,1,1,1] [1,0,1,0,1]
输出:
最长连续公共子序列为2,[0,1]
最长公共子序列(可不连续)为3,[1,1,1]
最长连续公共子序列
leetcode:https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]:
A
数
组
前
i
个
和
B
数
组
前
j
个
中
的
满
足
要
求
子
序
列
的
最
长
值
A 数组前i个和B数组前j个中的满足要求子序列的最长值
A数组前i个和B数组前j个中的满足要求子序列的最长值
状
态
方
程
:
状态方程:
状态方程:
d
p
[
i
]
[
j
]
=
{
d
[
i
−
1
]
[
j
−
1
]
+
1
if(
A
[
i
]
=
=
B
[
j
]
)
0
else
dp[i][j]= \begin{cases} d[i-1][j-1] + 1 & \text {if($A[i] == B[j]) $} \\ 0 & \text {else} \end{cases}
dp[i][j]={d[i−1][j−1]+10if(A[i]==B[j])else
因
为
要
求
连
续
,
只
要
间
断
,
就
是
0
因为要求连续,只要间断,就是0
因为要求连续,只要间断,就是0
class Solution {
public:
int findLength(vector<int>& A, vector<int>& B) {
int n = A.size();
int m = B.size();
int dp[n+2][m+2];
int maxn = 0;
memset(dp,0,sizeof(dp));
for(int i = 1 ;i <= n;i++){
for(int j = 1;j <= m;j++){
if(A[i-1] == B[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
maxn = max(dp[i][j],maxn);
}
}
return maxn;
}
};
最长公共子序列(可以不连续):类似于最长递增子序列
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]:
A
数
组
前
i
个
和
B
数
组
前
j
个
中
的
满
足
要
求
子
序
列
的
最
长
值
A 数组前i个和B数组前j个中的满足要求子序列的最长值
A数组前i个和B数组前j个中的满足要求子序列的最长值
状
态
方
程
:
状态方程:
状态方程:
d
p
[
i
]
[
j
]
=
{
d
[
i
−
1
]
[
j
−
1
]
+
1
if(
A
[
i
]
=
=
B
[
j
]
)
m
a
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
else
dp[i][j]= \begin{cases} d[i-1][j-1] + 1 & \text {if($A[i] == B[j]) $} \\ max(dp[i-1][j],dp[i][j-1]) & \text {else} \end{cases}
dp[i][j]={d[i−1][j−1]+1max(dp[i−1][j],dp[i][j−1])if(A[i]==B[j])else
如
果
间
断
,
那
么
当
前
的
最
大
值
就
是
前
面
状
态
的
值
中
的
最
大
值
如果间断,那么当前的最大值就是前面状态的值中的最大值
如果间断,那么当前的最大值就是前面状态的值中的最大值
class Solution {
public:
int findLength(vector<int>& A, vector<int>& B) {
int n = A.size();
int m = B.size();
int dp[n+2][m+2];
memset(dp,0,sizeof(dp));
for(int i = 1 ;i <= n;i++){
for(int j = 1;j <= m;j++){
if(A[i-1] != B[j-1]){
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
else
dp[i][j] = dp[i-1][j-1] + 1;
}
}
return dp[n][m];
}
};
区别
也正是这个原因,使得连续求最大需要遍历求最大,不连续求最大则是dp[n][m] 就是最大值。