题目

26年7月20日(首刷看解)
Go
func longestCommonSubsequence(text1 string, text2 string) int {
//dp[i][j],表示tset1[0~i-1]和text2[0~j-1]的最长公共子序列的长度
dp:=make([][]int,len(text1)+1)
for i,_ :=range dp{
dp[i]=make([]int,len(text2)+1)
}
for i:=1;i<=len(text1);i++{
for j:=1;j<=len(text2);j++{
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])
}
}
}
return dp[len(text1)][len(text2)]
//这道题需要演算一下例子
}
思路
这里变成求非连续的相同序列,和连续属于两种题型
非连续的dp数组定义是dp[i][j],表示text1[0~i-1]和text2[0~j-1]的最长公共子序列的长度,总之这一次不是以某一个元素结尾,而是从0一直到当前这个数字考虑。主要原因就是非连续,意味着只保持相对顺序,可以跳过元素。
那么递推公式有两种情况
第一种:当前这一对匹配
那么沿用之前连续时的递推公式dp[i][j]=dp[i-1][j-1]+1
第二种:当前这一对不匹配
当前这一对不匹配,不意味着断开了要重新计算了,因为可以从之前的位置继续找,
当前的i与j不匹配,但是当前的i可能和j之前的0~j-1,是一样的
也有可能j和i之前的0~i-1是相同的,这些都是满足要求的
所以递推公式dp[i][j]=max(dp[i-1][j],dp[i][j-1])
看到这个递推公式其实我也会后来想,如果dpi-1j或者dpij-1也是不匹配呢?仍然是默认的0?
其实总有一对他是匹配的,匹配后的长度值会不断的挨着传递,不用担心这个问题。
所以把两种情况合起来就是完整的递推公式
最后返回值,注意我们的dp数组含义已经发生变化 ,这里不再需要维护最大值,因为最大值一直在dp之间从前往后传递,所以返回dp[len(text1)][len(text2)]没问题