当前位置:   article > 正文

【DP】【LCS】最长公共子序列及其应用_最长公共子序列实际应用

最长公共子序列实际应用

  LCS 是很经典的 DP 问题,很多公司面试都会考,也有很多问题可以用 LCS 解决:

  1. LeetCode - 1143. Longest Common Subsequence 最长公共子序列(就是 LCS
  2. LeetCode - 583. Delete Operation for Two Strings 将两个字符串删除为相同字符串最少删除字符数
  3. LeetCode - 516. Longest Palindromic Subsequence 最长回文子序列(LPS
  4. LeetCode - 1092. Shortest Common Supersequence 最短公共超序列
一、Longest Common Subsequence(LCS)

Given two strings text1 and text2, return the length of their longest common subsequence.
A subsequence of a string is a new string generated from the original string with some characters(can be none) deleted without changing the relative order of the remaining characters. (eg, “ace” is a subsequence of “abcde” while “aec” is not).
A common subsequence of two strings is a subsequence that is common to both strings.
If there is no common subsequence, return 0.

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.

  LCS 重点就是想明白递推公式:

  • if text1[i] == text2[j],那么 lcs[i + 1][j + 1] = lcs[i][j] + 1
  • else,lcs[i + 1][j + 1] = max(lcs[i][j + 1], lcs[i + 1][j])

  这种二维矩阵 DP 问题,一般 DP 矩阵都会比数据多一个大小的位置,这样方便初始化,如下图,将所有初始化为0:

  AC 代码如下:

int longestCommonSubsequence(string text1, string text2) {
    const int len1 = text1.length(), len2 = text2.length();
    vector<vector<int>> lcs(len1 + 1, vector<int>(len2 + 1, 0));
    for(int i = 0; i < len1; ++i)
        for(int j = 0; j < len2; ++j) {
            if(text1[i] == text2[j])
                lcs[i + 1][j + 1] = lcs[i][j] + 1;
            else
                lcs[i + 1][j + 1] = max(lcs[i][j + 1], lcs[i + 1][j]);
        }
    return lcs[len1][len2];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
二、Delete Operation for Two Strings

  像 LeetCode - 583. Delete Operation for Two Strings 这种题,用 LCS 很容易,算出两个字符串的最长公共子序列之后,用两个字符串的长度分别减这个公共子序列的长度,就是了:

int minDistance(string word1, string word2) {
	return word1.length() + word2.length() - 2 * longestCommonSubsequence(word1, word2);
}
  • 1
  • 2
  • 3
三、Longest Palindromic Subsequence(LPS)

  像 LeetCode - 516. Longest Palindromic Subsequence,最长回文子序列的题也可以用 LCS 解决,就是将输入的字符串 s,翻转成 s’然后对 s 和 s’进行 LCS 的计算,当然 LPS 还有自己的 DP 方法,具体可以参考 https://blog.csdn.net/Bob__yuan/article/details/99693725

int longestPalindromeSubseq(string s) {
    string s_rev = s;
    reverse(s_rev.begin(), s_rev.end());
    return longestCommonSubsequence(s, s_rev);
}
  • 1
  • 2
  • 3
  • 4
  • 5
四、Shortest Common Supersequence

  最短公共超序列,就是就是上边第二题的延伸,找出一个字符串 s,通过删除任意位置字符,可以得到 s1 和 s2 两个字符串,找出最短的 s。其实就是找出 lcs 的路径,不止是长度。所以 dp 的二维矩阵中存储的就不是当前 lcs 的长度了,而是当前的 lcs 字符串。然后用最终的 lcs 字符串,用过一个字符一个字符的比较,将需要添加的字符添加到的结果中即可。

string LCS(const string& s1, const string& s2) {
    const int len1 = s1.length(), len2 = s2.length();
    vector<vector<string>> lcs(len1 + 1, vector<string>(len2 + 1, ""));
    for(int i = 0; i < len1; ++i)
        for(int j = 0; j < len2; ++j) {
            if(s1[i] == s2[j])
                lcs[i + 1][j + 1] = lcs[i][j] + s1[i];
            else
                lcs[i+ 1][j + 1] = lcs[i + 1][j].length() > lcs[i][j + 1].length() ? lcs[i + 1][j] : lcs[i][j + 1];
        }
    return lcs[len1][len2];
}

string shortestCommonSupersequence(string str1, string str2) {
    string lcs = LCS(str1, str2), res;
    int i = 0, j = 0;
    for(const char& c : lcs) {
        while(str1[i] != c)
            res += str1[i++];
        while(str2[j] != c)
            res += str2[j++];
        res += c;
        ++i, ++j;
    }
    return res + str1.substr(i) + str2.substr(j);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/87374
推荐阅读
相关标签
  

闽ICP备14008679号