动态规划算法学习(四)leetcode:1143 最长公共子序列

一、题:给定两个字符串text1和text2,返回这两个字符串的最长公共子序列的长度。如果不存在公共子序列,返回0。

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

二、思路

1.dp数组的含义

dp[i][j]表示:长度为[0-(i-1)]的字符串text1与长度为[0-(j-1)]的字符串text2的最长公共子序列数为dp[i][j]

定义为i-1和j-1可以看二维数组定义后的图,帮助理解

text1/text2ace
********
a**dp[1][1]****
b********
c********
d****dp[4][2]**
e********

例如表中的dp[1][1]表示text1[1-1]=text1[0](‘a’)之前的字符串与text2[1-1]=text2[0](‘a’)之前的字符串的最大公共子序列。

表中的dp[4][2]表示text1[4-1]=text2[3](‘d’)之前的字符串与text2[2-1]=text1[1](‘c’)之前的字符串的最大公共子序列

可以看出每个二维数组的值dp[i][j]正上方和正左方对应的字符串值在数组里就是text1[i-1]和text2[j-1]

2、递推公式

最大公共子序列问题也分为两种情况:1.text1[i-1]与text2[j-1]相同  2.text1[i-1]与text2[j-1]不相同

相同:如果text1[i-1]与text2[j-1]相同,此时又多了一个公共子序列元素,所以dp[i][j]=dp[i-1][j-1]+1

不相同:如果text1[i-1]与text2[j-1]不相同,那么就要看dp[i-1][j]与dp[i][j-1]中最大的公共子序列,即text1[i-2]与text2[j-1]的最长公共子序列和text1[i-1]与text2[j-2]的最长公共子序列的最大值

即dp[i][j]=max(dp[i-1][j],dp[i][j-1])

3、dp数组初始化

从递推公式可以看出dp[i][j]是由三个方向递推而来的即dp[i-1][j-1](dp[i][j]的左右上角)、dp[i-1][j](dp[i][j]的正上方)、dp[i][j-1](dp[i][j]的正左方)

因此应该初始化的二维数组为dp[i][0]和dp[0][j]。

dp[i][0]表示text1[0--(i-1)]和空字符串的最长公共子序列,那么自然是0,所以dp[i][0]=0,同理dp[0][j]=0

其余的二维数组值会随着递推公式计算补充,会被覆盖掉,所以复制多少都可以,这里全部赋值为0了

4、遍历顺序

从递推公式的递推dp[i][j]的三个方向可以看出,是从前向后,从左到右的

5、举例推导dp数组

dp[1][1]=1,因为text1[0]与text2[0]相等,所以最大公共子序列值为0+1=1

dp[1][2]=1,因为text1[0]与text2[1]不相等,dp[0][2]=0,dp[1][1]=1,最大值为1,所以最长公共子序列为1

。。。。

dp[4][2]=2,因为text1[3]与text2[1]不相同,dp[3][2]=2,dp[4][1]=1,最大值为2,所以最长公共子序列为2

。。。。

三、代码(Python3)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值