最长公共子序列

GitHub跳转原题关系图返回列表

二维 DP:字符相等时 dp[i][j]=dp[i-1][j-1]+1,不等时取 max(dp[i-1][j], dp[i][j-1])。

OJ: leetcodecn

题目 ID: longest-common-subsequence

难度:普及+/提高

标签:动态规划字符串

日期: 2026-07-29 12:57

题意

求两个字符串的最长公共子序列长度。

思路

dp[i][j] 表示 text1[0..i-1]text2[0..j-1] 的 LCS 长度。若 text1[i-1] == text2[j-1],则 dp[i][j] = dp[i-1][j-1] + 1;否则 dp[i][j] = max(dp[i-1][j], dp[i][j-1])

代码

cpp
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    int longestCommonSubsequence(string a, string b) {
        int m = a.size(), n = b.size();
        vector<int> dp(n + 1, 0);
        for (int i = 1; i <= m; i++) {
            int prev = 0;
            for (int j = 1; j <= n; j++) {
                int tmp = dp[j];
                if (a[i - 1] == b[j - 1])
                    dp[j] = prev + 1;
                else
                    dp[j] = max(dp[j], dp[j - 1]);
                prev = tmp;
            }
        }
        return dp[n];
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    string a, b;
    cin >> a >> b;
    cout << Solution().longestCommonSubsequence(a, b) << '\n';
    return 0;
}
python
#!/usr/bin/env python3
class Solution:
    def longestCommonSubsequence(self, a: str, b: str) -> int:
        m, n = len(a), len(b)
        dp = [0] * (n + 1)
        for i in range(1, m + 1):
            prev = 0
            for j in range(1, n + 1):
                tmp = dp[j]
                if a[i - 1] == b[j - 1]:
                    dp[j] = prev + 1
                else:
                    dp[j] = max(dp[j], dp[j - 1])
                prev = tmp
        return dp[n]


def main():
    a = input().strip()
    b = input().strip()
    print(Solution().longestCommonSubsequence(a, b))


if __name__ == "__main__":
    main()

复杂度

  • 时间复杂度:O(mn)O(mn)
  • 空间复杂度:O(mn)O(mn)

总结

LCS 是二维 DP 的经典:相等时沿对角线延伸,不等时取上方或左方的较大值。