开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情
最长公共子序列
代表题:「1143. 最长公共子序列」
一个字符串的 子序列 是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
子序列的定义注定了不连续的个数也可以统计到一个。
一般使用动态规划解决该问题,状态定义,dp[i][j]其实就是text1[0:i]和text2[0:j]的最长公共子序列的个数。
当text1[i]==text2[j],因此最长公共子序列增加1,dp[i][j]=dp[i-1][j-1]+1。
当text1[i]!=text2[j],dp[i][j]应该是dp[i-1][j]和dp[i][j-1]的最大值。
func longestCommonSubsequence(text1 string, text2 string) int {
m,n:=len(text1),len(text2)
// dp[i][j]表示text1[i]和text2[j]的公共子序列个数
dp:=make([][]int,m+1)
for i:=0;i<=m;i++{
dp[i]=make([]int,n+1)
}
for i:=1;i<=len(text1);i++{
for j:=1;j<=len(text2);j++{
if text1[i]==text2[j]{
dp[i][j]=dp[i-1][j-1]+1
}else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
}
}
}
return dp[m][n]
}
func max(a,b int)int{
if a>b{
return a
}
return b
}
最长公共子串
代表题目:718. 最长重复子数组
最长公共子串问题是寻找最长的字符串问题。该字符串是两个字符串的子串。与最长公共子序列不同,子串需要在原始字符串中占据连续的位置。
如字符串 ABABC和BABACA的最长公共子串是 BABC,而其他公共子串有ABC、A、AB、B、BA、BC、C。
该问题也可以使用动态规划来解决。令 dp[i][j] 表示 A[i:] 和 B[j:] 的最长公共前缀,那么答案即为所有 dp[i][j] 中的最大值。整个过程倒序累加。
func findLength(nums1 []int, nums2 []int) int {
// 连续公共
m,n:=len(nums1),len(nums2)
// dp[i][j]表示nums1[A:]和nums[B:]的最长公共前缀
// dp[m][n]=0 方便计算
dp:=make([][]int,m+1)
for i:=0;i<=m;i++{
dp[i]=make([]int,n+1)
}
res:=0
for i:=m-1;i>=0;i--{
for j:=n-1;j>=0;j--{
if nums1[i]==nums2[j]{
dp[i][j]=dp[i+1][j+1]+1
}else{
dp[i][j]=0
}
res=max(res,dp[i][j])
}
}
return res
}
func max(a,b int)int{
if a>b{
return a
}
return b
}