最长公共子序列

不羁岁月 提交于 2020-02-27 19:47:58

一、题目

1、来源

力扣题号1143:https://leetcode-cn.com/problems/longest-common-subsequence/

2、题目描述

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。

若这两个字符串没有公共子序列,则返回 0。

二、解题思路

1、dp定义

这是一个二维DP问题,需要求解的是两个字符串最长公共子序列的长度,一般我们是可以直接将dp[i][j]定义为题目求解的答案(也有部分情况还需要对dp进行处理),所以这里我们定义dp[i][j]为字符串text1[0...i]与字符串text2[0...j]的最长公共子序列

2、初始状态

两个字符串分别为text1text2,假设text1="abc",text2="de",则dp形如:

行为text1,列为text2 “” d e
“”
a
b
c

两个空串分别表示text1为空和text2为空。
(1) 当text1为空时,text2的任意一个字符与text1的公共子序列都为空,即dp[0][j]=0, j>=0 && j<=text2.size(),j取等号是因为我们表格中考虑了空串,所以dp的行为text1.size()+1,列为text2.size()+1
(2) 当text2为空时,有dp[i][0]=0, i>=0 && i<=text1.size(),理由同上

3、转移方程

(1) 当text1[i]=text2[j]时,则有dp[i][j]=dp[i-1][j-1]+1

text1 a b ... c d text1(i)
text2 d b ... c d text2(j)

可以看到text1[i]text2[j]的最长公共子序列为text1[i-1]text2[j-1]的最长公共子序列+text1[i]或text2[j]
(2)当text1[i]!=text2[j]时,则分为三种情况:
①通过text1[i-1]text2[j-1]计算,即dp[i][j]=dp[i-1][j-1]

text1 a b ... c d text1(i)
text2 d b ... c d text2(j)

②通过text1[i-1]text2[j]计算,即dp[i][j]=dp[i-1][j]

text1 a b ... c d text1(i)
text2 d b ... c d text2(j)

③通过text1[i]text2[j-1]计算,即dp[i][j]=dp[i][j-1]

text1 a b ... c d text1(i)
text2 d b ... c d text2(j)

从上面三种情况可以看到,(text1[i-1],text2[j-1])的最长公共子序列不可能比(text1[i-1],text2[j])或者(text1[i],text2[j-1])的长。所以dp[i][j]=max(dp[i-1][j],dp[i][j-1])

三、C++源码

int longestCommonSubsequence(string text1, string text2) {
        int len1=text1.size();
        int len2=text2.size();
        int dp[len1+1][len2+1]={0}; // 行为text1的长度
        for(int i=0;i<=len1;i++) // 类比text2为空串的情况(即列为空串)
            dp[i][0]=0; 
        for(int j=0;j<=len2;j++) // 类型text1为空串的情况,即行为空串
            dp[0][j]=0;
        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){ // 将text1的每个字符逐个与text2比较
                if(text1[i-1]==text2[j-1])
                    dp[i][j]=dp[i-1][j-1]+1;
                else
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]); // dp[i-1][j-1]的长度始终比这两个短
            }
        }
        return dp[len1][len2];
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!