最长公共子序列(Longest Common Subsequence,简称 LCS)是指在两个或多个序列中,找到一个最长的子序列,该子序列在所有输入序列中以相同的顺序出现,但不一定连续。
- 例如:序列 “ABCBDAB” 和 “BDCAB” 的 LCS 是 “BCAB”(长度为 4),子序列中的元素顺序与原序列一致,但位置不要求连续。
动态规划是求解 LCS 的高效方法,核心思路是通过构建二维表格存储子问题的解,避免重复计算。
设两个序列为X[0..m-1]和Y[0..n-1],定义dp[i][j]表示X[0..i-1]和Y[0..j-1]的 LCS 长度。
- 若
X[i-1] == Y[j-1](当前元素相同),则dp[i][j] = dp[i-1][j-1] + 1(LCS 长度加 1)。
- 若
X[i-1] != Y[j-1](当前元素不同),则dp[i][j] = max(dp[i-1][j], dp[i][j-1])(取去掉 X 最后一个元素或 Y 最后一个元素后的 LCS 最大值)。
dp[0][j] = 0(X 为空序列时,LCS 长度为 0)。
dp[i][0] = 0(Y 为空序列时,LCS 长度为 0)。
通过填充后的dp表格,从dp[m][n]开始反向追溯:
- 若
X[i-1] == Y[j-1],则该元素是 LCS 的一部分,同时向左上方移动(i--, j--)。
- 否则,向
dp[i-1][j]或dp[i][j-1]中值较大的方向移动(若相等,可任选其一)。
以X = "ABCBDAB"(长度 7)和Y = "BDCAB"(长度 5)为例:
- 构建
8x6的dp表格(包含 0 行 0 列),填充后dp[7][5] = 4,即 LCS 长度为 4。
- 回溯可得 LCS 为 “BCAB”(或 “BDAB”,因存在多个解)。
该算法时间复杂度为O(m*n),空间复杂度为O(m*n)(可优化为O(min(m,n)))。