LongDz 的数字文墨提案

1143. 最长公共子序列

3 min

题目

1143. 最长公共子序列 中等

解法:动态规划

思路

核心思想是动态规划,通过构建二维DP表存储所有前缀子串的最优解。

正确性基于最优子结构:每个状态 dp[i][j] 都表示 text1 前 i 个字符与 text2 前 j 个字符的最长公共子序列长度。当字符匹配时,问题可分解为子问题 dp[i-1][j-1] 加1;不匹配时,最优解必然包含于跳过 text1[i-1] 或 text2[j-1] 的两种情况之一,因此取最大值可保证不遗漏最优解。

  • Step 1: 初始化 (m+1)×(n+1) 的DP数组,全部置0
  • Step 2: 双重循环遍历两个字符串的所有字符位置
  • Step 3: 若当前字符匹配,则 dp[i][j] = dp[i-1][j-1] + 1
  • Step 4: 若字符不匹配,则 dp[i][j] = max(dp[i-1][j], dp[i][j-1])
  • Step 5: 返回 dp[m][n] 作为最终结果

复杂度

  • 时间复杂度: O(m×n)O(m \times n),其中 m 和 n 为两字符串长度,需填充整个DP表。
  • 空间复杂度: O(m×n)O(m \times n),用于存储二维DP数组。

代码

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