1143. 最长公共子序列

1143. 最长公共子序列

题目链接:1143. 最长公共子序列(中等)

给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例 1:

输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace" ,它的长度为 3 。

示例 2:

输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc" ,它的长度为 3 。

示例 3:

输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0 。

提示:

  • 1 <= text1.length, text2.length <= 1000

  • text1text2 仅由小写英文字符组成。

解题思路

本题与718. 最长重复子数组 很相似,但718. 最长重复子数组 要求是连续的,本题不要求连续,但要求要有顺序(例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列)。

该题也是运用动态规划来作答。

C++

class Solution {
public:
    // 该题不要求连续,但要求顺序(顺序不能颠倒)
    int longestCommonSubsequence(string text1, string text2) {
        // 1. dp数组的含义
        // dp[i][j] :以下标i - 1为结尾的 text1,和以下标j - 1为结尾的 text2,最长最长公共子序列为dp[i][j]
        // 注意:在遍历dp[i][j]的时候i 和 j都要从1开始的,这就减轻了初始化dp数组的工作
        // 3. 初始化
        // 根据dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的!它们是为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;
        // 所以dp[i][0] 和dp[0][j]初始化为0。
        vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
        // 4. 遍历顺序:外层for循环遍历 text1,内层for循环遍历 text2。
        for (int i = 1; i <= text1.size(); i++) {
            for (int j = 1; j <= text2.size(); j++) {
                // 2. 递推公式
                // 如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;
                // 如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。
                if (text1[i - 1] == text2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1; // 注意还需要考虑 “abcde” 和 “aec” 这种情况
                } else {
                    dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
                }
            }
        }
        return dp[text1.size()][text2.size()];
    }
};

JavaScript

/**
 * @param {string} text1
 * @param {string} text2
 * @return {number}
 */
 var longestCommonSubsequence = function(text1, text2) {
    const dp = Array(text1.length + 1).fill().map(item => Array(text2.length + 1).fill(0));
    for (let i = 1; i <= text1.length; i++) {
        for (let j = 1; j <= text2.length; j++) {
            if (text1[i - 1] === text2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
            }
        }
    }
    return dp[text1.length][text2.length];
};

 

posted @ 2022-03-16 11:14  wltree  阅读(30)  评论(0编辑  收藏  举报