• 1143. Longest Common Subsequence


    问题:

    给定两个字符串,求他们的最长公共子序列的长度。

    Example 1:
    Input: text1 = "abcde", text2 = "ace" 
    Output: 3  
    Explanation: The longest common subsequence is "ace" and its length is 3.
    
    Example 2:
    Input: text1 = "abc", text2 = "abc"
    Output: 3
    Explanation: The longest common subsequence is "abc" and its length is 3.
    
    Example 3:
    Input: text1 = "abc", text2 = "def"
    Output: 0
    Explanation: There is no such common subsequence, so the result is 0.
     
    Constraints:
    1 <= text1.length <= 1000
    1 <= text2.length <= 1000
    The input strings consist of lowercase English characters only.
    

      

    解法:DP(动态规划)

    1.确定【状态】:

    • 字符串text1的第i个字符:text1[i]
    • 字符串text2的第j个字符:text2[j]

    2.确定【选择】:分两种情况

    • text1[i] == text2[j]:
      • 前一个字符状态(公共序列长度)+1:  dp[i-1][j-1] + 1
    • text1[i] != text2[j]:有以下3种情况,取最大值。
      • 只有text1[i]是最终公共子序列的一个字符    -> =上一个包含text1[i]而不包含text2[j]的字符状态:dp[i][j-1]
      • 只有text2[j]是最终公共子序列的一个字符   -> =上一个不包含text1[i]而包含text2[j]的字符状态:dp[i-1][j]
      • 两个字符都不是最终公共子序列的一个字符 -> =上一个既不包含text1[i]又不包含text2[j]的字符状态:dp[i-1][j-1]
        • ★由于dp[i-1][j-1]一定<=dp[i][j-1] or dp[i-1][j],因此可以省略比较dp[i-1][j-1]

    3. dp[i][j]的含义:

    对比到text1的第 i 个字符,text2的第 j 个字符为止,两个字符串的最大公共子序列长度。

    4. 状态转移:

    dp[i][j]=

    • (text1[i] == text2[j]):=前一个字符状态+1:dp[i-1][j-1] + 1
    • (text1[i] != text2[j]):=max {
      • 上一个包含text1[i]字符的状态:dp[i][j-1]
      • 上一个包含text2[j]字符的状态:dp[i-1][j]
      • 上一个text1[i]text2[j]都不包含的状态:dp[i-1][j-1](★可省略)    }

    5. base case:

    • dp[0][j]=0:text1为空串,则其与text2的公共子序列也一定为空串,长度为0。
    • dp[i][0]=0:text2为空串,则其与text1的公共子序列也一定为空串,长度为0。

    代码参考:

     1 class Solution {
     2 public:
     3     //dp[i][j]:until text1[i],text2[j]. the max length of the LCS
     4     //case_1: text1[i]==text2[j]:
     5     //        this character must be in LCS. we need add 1 to pre status:dp[i-1][j-1].
     6     //        =dp[i-1][j-1]+1
     7     //case_2: text1[i]!=text2[j]
     8     //        text1[i] or text2[j] may in LCS. we choose the max of these possibilities.
     9     //        if text1[i] is in LCS, 
    10     //        = dp[i][j-1]
    11     //        if text2[j] is in LCS, 
    12     //        = dp[i-1][j]
    13     //        if none of them is in LCS, 
    14     //        = dp[i-1][j-1]
    15     // note: dp[i-1][j-1]<=dp[i-1][j](dp[i][j-1]) ,so we can ignore it
    16     //        =max(dp[i][j-1],dp[i-1][j])
    17     //base case:
    18     //dp[i][0]=0
    19     //dp[0][j]=0
    20     int longestCommonSubsequence(string text1, string text2) {
    21         int m = text1.length(), n = text2.length();
    22         vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
    23         for(int i=1; i<=m; i++) {
    24             for(int j=1; j<=n; j++) {
    25                 if(text1[i-1]==text2[j-1]) {
    26                     dp[i][j]=dp[i-1][j-1]+1;
    27                 } else {
    28                     dp[i][j]=max(dp[i-1][j], dp[i][j-1]);
    29                 }
    30             }
    31         }
    32         return dp[m][n];
    33     }
    34 };

    ♻️ 优化:

    空间复杂度:2维->1维

    去掉 i 

    压缩所有行到一行。

    左上角dp[i-1][j-1]会被下面的dp[i][j-1]覆盖,因此引入变量pre,在更新dp[i][j-1]之前,保存dp[i-1][j-1]

    代码参考:

     1 class Solution {
     2 public:
     3     int longestCommonSubsequence(string text1, string text2) {
     4         int m = text1.length(), n = text2.length();
     5         vector<int> dp(n+1, 0);
     6         for(int i=1; i<=m; i++) {
     7             int pre = 0;
     8             for(int j=1; j<=n; j++) {
     9                 int tmp = dp[j];
    10                 if(text1[i-1]==text2[j-1]) {
    11                     dp[j]=pre+1;
    12                 } else {
    13                     dp[j]=max(dp[j], dp[j-1]);
    14                 }
    15                 pre = tmp;
    16             }
    17         }
    18         return dp[n];
    19     }
    20 };
  • 相关阅读:
    leetcode 443: String Compression,357: Count Numbers with Unique Digits
    C++ 中 freopen()函数的用法
    filter
    map
    os.listdir
    os.path.join
    assert
    numpy中的axis和Pytorch中的dim参数
    mac中qq接收视频存放的位置
    requests
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/13621859.html
Copyright © 2020-2023  润新知