AcWing 272. 【Java】最长公共上升子序列
原题链接
中等
作者:
tt2767
,
2020-01-08 00:40:26
,
所有人可见
,
阅读 800
/*
1. 状态定义: 表示最长公共子序列的长度 ->
f[i][j] = A[1...i]和B[1...j]的公共子序列长度,并且以A[i]结尾 (和视频相反)
2. 状态计算: 按最后一位B[j]分为2个集合并取最大值
2.1 不包含B[j]的公共子序列长度即 f[i][j-1]
2.2 包含B[j]的公共子序列长度即为下列子集:
【A[0]&B[1...j-1] <- A[i]&B[j] = f[0][j-1] + 1】
【A[0,1]&B[1...j-1] <- A[i]&B[j] = f[1][j-1] + 1】
....
【A[0...i-1]&B[1...j-1] <- A[i]&B[j] = f[i-1][j-1] + 1】
3. 边界条件: f[i][0] = 1 ?
*/
import java.util.*;
public class Main{
int maxN = 3002;
int[] A = new int[maxN];
int[] B = new int[maxN];
int[][] f = new int[maxN][maxN];
void run(){
int n = jin.nextInt();
for (int i = 1 ; i <= n ; i++) A[i] = jin.nextInt();
for (int i = 1 ; i <= n ; i++) B[i] = jin.nextInt();
for (int j = 1 ; j <= n ; j++){
int maxV = 1;
for (int i = 1 ; i <= n ; i++){ // A的循环在内层是方便更新maxV
f[i][j] = f[i][j-1]; // 不包含b[j]
if (A[i] == B[j]) f[i][j] = Math.max(f[i][j], maxV); // 包含b[j], 为什么条件是相等呢?因为公共啊。。。
// if (f[i][j-1] < maxv) maxv = Math.max(f[i][j-1], maxv);
if (A[i] < B[j]) maxV = Math.max(f[i][j-1] + 1, maxV); // i 是每次遍历的值,j是不变的,即B[j]=A[last],满足上升要保证<
}
}
//暴力做法 : B 在内层循环
// for (int i = 1 ; i <= n ; i++){
// for (int j = 1 ; j <= n ; j++){
// f[i][j] = f[i][j-1];
// if (A[i] != B[j]) continue;
// int maxV = 1;
// for (int k = 1 ; k < i; k++) if (A[k] < B[j]) maxV = Math.max(maxV, f[k][j-1] + 1);
// f[i][j] = Math.max(maxV, f[i][j]);
// }
// }
int res = 0;
for (int i = 1 ; i <= n ;i++) res = Math.max(res, f[i][n]);
System.out.println(res);
}
Scanner jin = new Scanner(System.in);
public static void main(String[] args) throws Exception {new Main().run();}
}