最长公共子序列(Longest Common Subsequence)是动态规划的经典二维问题,广泛应用于 diff 工具、DNA 序列比对、版本控制等领域。
一、问题定义
Mermaid · 渲染中(下方为源码)
graph TD A[s1,s2] --> B[二维DP表] B --> C[字符相等+1] C --> D[否则取max]
给定两个字符串 s1 和 s2,找出它们的最长公共子序列的长度。子序列不要求连续。
s1 = "abcde"
s2 = "ace"
LCS = "ace",长度 3
二、O(mn) 动态规划
状态定义
dp[i][j] = s1[0..i-1] 和 s2[0..j-1] 的 LCS 长度
转移方程
if s1[i-1] == s2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
代码实现
int longestCommonSubsequence(String s1, String s2) {
int m = s1.length(), n = s2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}