最长公共子序列(Longest Common Subsequence)

描述

最长公共子序列(Longest Common Subsequence)_第1张图片
标签

  • 字符串;
  • 动态规划经典问题;

思路

变量说明:

  • 字符串text1长度为:m
  • 字符串text2长度为:n
  • 二维数组dp:m行n列

递归方程:

  • d p [ i ] [ j ] dp[i][j] dp[i][j]表示 t e x t 1 text1 text1 i i i 个字符构成的子串与 t e x t 2 text2 text2 j j j 个字符构成的子串的最长公共子序列;
  • t e x t 1 [ i ] = = t e x t 2 [ j ] text1[i] == text2[j] text1[i]==text2[j] 时, d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 dp[i][j] = dp[i - 1][j - 1] + 1 dp[i][j]=dp[i1][j1]+1
  • t e x t 1 [ i ] ! = t e x t 2 [ j ] text1[i] != text2[j] text1[i]!=text2[j] 时, d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) dp[i][j]=max(dp[i1][j],dp[i][j1])

即:
d p [ i ] [ j ] = { d p [ i − 1 ] [ j − 1 ] + 1 t e x t 1 [ i ] = = t e x t 2 [ j ] m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) t e x t 1 [ i ] ! = t e x t 2 [ j ] dp[i][j] = \begin{cases} dp[i - 1][j - 1] + 1 & text1[i] == text2[j] \\ max(dp[i - 1][j], dp[i][j - 1]) & text1[i] != text2[j] \end{cases} dp[i][j]={dp[i1][j1]+1max(dp[i1][j],dp[i][j1])text1[i]==text2[j]text1[i]!=text2[j]

空间优化:

  • 上述算法,空间复杂度为 O ( m ∗ n ) O(m * n) O(mn)
  • 通过递归方程可发现,dp只会用到当前行和上一行,不会用到其它行,因此,可以对其优化使其空间复杂度为 O ( n ) O(n) O(n)
  • 优化方法,参考代码,进行理解;

代码

int longestCommonSubsequence(string text1, string text2) {
    if(text1.empty() || text2.empty())
        return 0;
        
    int m = text1.size();
    int n = text2.size();
    vector dp(n, 0);
    for(int i = 0; i < m; ++i)
    {
        int left_top = dp[0];
        if(text1[i] == text2[0])
            dp[0] = 1;
        for(int j = 1; j < n; ++j)
        {
            int temp = dp[j];
            dp[j] = text1[i] == text2[j] ? left_top + 1 : max(dp[j - 1], dp[j]);
            left_top = temp;
        }
    }
    return dp[n - 1];
}

练习题

LeetCode 1143. Longest Common Subsequence

你可能感兴趣的:(#,LeetCode,#,字符串,#,动态规划)