算法日记:最长公共子问题

75 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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
}

参考

www.techiedelight.com/zh/longest-… leetcode.cn/problems/ma…