[算法系列之十九]最长公共子序列

简介:

题目

最长公共子序列

分析

有两个字符串S1和S2,求一个最长公共子串,即求字符串S3,它们同时是S1和S2的子串,且要求它们的长度最长,并确定这个长度。这个问题我们称之为最长公共子序列问题。
与求最长递增子序列一样,我们首先将原问题分割成一些子问题,我们用dp[i][j]表示S1中前i个字符和S2中前j个字符分别组成的两个前缀字符串的最长公共子串长度。显然的,当i,j较小时我们可以直接给出答案,如dp[0][j] 必等于0。那么,假设我们已经求的dp[i][j](0 <= i < x,0 <= j < y)的所有值,考虑如何在这些值继而推的dp[x][y],求的S1前x个字符组成的前缀子串和S2前y个字符组成的前缀子串的最长公共的子序列的长度。若S1[x] == S2[y],即S1中的第x个字符和S2中的第y个字符相同,同时由于他们都是各自前缀子串的最后一个字符,那么必存在一个最长的公共子串以S1[x]或S2[y]结尾。其他部分等价于S1中前x-1个字符和S2中前y-1个字符的最长公共子串。所以这个子串的长度比dp[x-1][y-1]增加1,即dp[x][y] = dp[x-1][y-1] + 1。相反的,若S1[x] != S2[y],此时其最长的公共子串长度为S1中前x-1个字符和S2中前y个字符的最长公共子串的长度与S1中前x个字符和S2中前y-1个字符的最长公共子串的长度的较大者,即在两种情况下得到的最长公共子串都不会因为其中一个字符串又增加了一个字符长度发生改变。综上所述,dp[x][y] = max{dp[x][y-1] , dp[x-1][y]}。
总结一下,最长公共子序列问题的递推条件:
假设有两个字符串S1和S2,其中S1长度为n,S2长度为m,用dp[i][j]表示S1前i个字符组成的前缀子串与S2前j个字符组成的前缀子串的最长公共子串长度,那么:

dp[0][j] = 0 (0 <= j <= m) 
dp[i][0] = 0 (0 <= i <= n)
dp[i][j] = dp[i-1][j-1] + 1 (S1[i] == S2[j])
dp[i][j] = max{dp[i][j-1],dp[i-1][j]} (S1[i] != S2[j]) 

代码

/*---------------------------------------------
*   日期:2015-02-12
*   作者:SJF0115
*   题目: 19.最长公共子序列
*   来源:算法系列
*   博客:
-----------------------------------------------*/
#include <iostream>
#include <algorithm>
using namespace std;


class Solution {
public:
    int LCS(string a,string b){
        int sizea = a.size();
        int sizeb = b.size();
        if(sizea <= 0 || sizeb <= 0){
            return 0;
        }//if
        int dp[sizea+1][sizeb+1];
        // 初始化
        for(int i = 0;i < sizea;++i){
            for(int j = 0;j < sizeb;++j){
                if(i == 0 || j == 0){
                    dp[i][j] = 0;
                }//if
            }//for
        }//for
        // 递推
        for(int i = 1;i <= sizea;++i){
            for(int j = 1;j <= sizeb;++j){
                if(a[i] == b[j]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }//else
                else{
                    dp[i][j] = max(dp[i][j-1],dp[i-1][j]);
                }//else
            }//for
        }//for
        return dp[sizea][sizeb];
    }
};


int main() {
    Solution solution;
    string a("BDCABA");
    string b("ABCBDAB");
    cout<<solution.LCS(a,b)<<endl;
}
目录
相关文章
|
算法 Python
Python OJ题典型算法:最长公共子序列
本文介绍了动态规划算法在解决最长公共子序列问题中的应用。通过详细的解题思路和代码实现,展示了如何利用动态规划算法高效地求解最长公共子序列的长度。这些技巧和方法对于理解和掌握动态规划算法以及解决其他类似问题具有重要意义。
303 0
|
算法
【面试算法——动态规划 20】最长公共子序列&& 不相交的线
【面试算法——动态规划 20】最长公共子序列&& 不相交的线
118 1
|
算法
代码随想录算法训练营第五十三天 | LeetCode 1143. 最长公共子序列、1035. 不相交的线、53. 最大子数组和
代码随想录算法训练营第五十三天 | LeetCode 1143. 最长公共子序列、1035. 不相交的线、53. 最大子数组和
97 1
算法练习Day53|1143.最长公共子序列 ● 1035.不相交的线 ● 53. 最大子序和 动态规划
算法练习Day53|1143.最长公共子序列 ● 1035.不相交的线 ● 53. 最大子序和 动态规划
|
存储 算法 Java
【软考总结】-<算法>动态规划法--最长公共子序列
公共子序列:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。(子序列Y中的字符在X中不一定是连续的。
268 0
|
算法 Java
《趣学算法-动态规划-最长的公共子序列》阅读笔记
《趣学算法-动态规划-最长的公共子序列》阅读笔记
203 0
《趣学算法-动态规划-最长的公共子序列》阅读笔记
|
存储 算法
【完虐算法】「字符串-最长公共子序列」全面总结
本来想要把「最长公共子序列」和「最长上升子序列」一起和大家把思路分享一下,都属于可以使用动态规划的思想进行解决。但貌似还是两块内容。 所以,今天先把「最长公共子序列」分享出来和大家聊聊。 后面再出一期把「最长上升子序列」详细的分享,后面这一期内容估计会比较多。
408 0
|
JavaScript 算法 前端开发
LCS 算法:Javascript 最长公共子序列
LCS 算法:Javascript 最长公共子序列
2823 0

热门文章

最新文章