@(labuladongのアルゴリズムに関するチートシート)[dp]
leetcode1143 。最長共通部分列
タイトル説明
問題解決のアイデア
参照:最長共通部分列問題を詳細に説明し、3つの動的計画問題を数秒で殺します
再帰
import java.util.Arrays;
class Solution {
/* 备忘录,消除重叠子问题 */
private int[][] memo;
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length(), n = text2.length();
/* 备忘录初始化,如果为-1,代表未计算 */
memo = new int[m + 1][n + 1];
for (int[] row : memo)
Arrays.fill(row, -1);
/* 计算 text1[0...m-1] 和 text2[0...n-1] 的lcs长度 */
return dp(text1, m, text2, n);
}
/* 定义:计算 text1[0...i-1] 和 text2[0...j-1] 的lcs长度 */
private int dp(String text1, int i, String text2, int j) {
/* base case */
if (i == 0 || j == 0) {
return 0;
}
/* 如果之前计算过,则直接返回备忘录记录的lcs长度 */
if (memo[i][j] != -1) {
return memo[i][j];
}
/* 当前在text1[i - 1]和text2[j - 1]处做选择 */
if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
memo[i][j] = 1 + dp(text1, i - 1, text2, j - 1);
} else {
memo[i][j] = Math.max(
dp(text1, i - 1, text2, j),
dp(text1, i, text2, j - 1)
);
}
return memo[i][j];
}
}
アレイ
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length(), n = text2.length();
/*
定义:dp[i][j]表示,text1[0...i-1] 和 text2[0...j-1]的lcs长度
目标:dp[m][n],即text1[0...m-1] 和 text2[0...n-1]的lcs长度
base case:dp[0][...] = dp[...][0] = 0
*/
int[][] dp = new int[m + 1][n + 1];
for(int i = 1; i <= m; i ++) {
for(int j = 1; j <= n; j ++) {
/* 当前在text1[i - 1]和text2[j - 1]处做选择 */
if(text1.charAt(i - 1) == text2.charAt(j - 1)) {
// text1[i-1] 和 text2[j-1] 必然在 lcs 中
dp[i][j] = 1 + dp[i - 1][j - 1];
} else {
// text1[i-1] 和 text2[j-1] 至少有一个不在 lcs 中
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}
}