【算法笔记】最长公共子序列

问题

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

问题分析

本题是求两个字符串的最长公共子序列,是求存在的最优值,可判断为动态规划问题,解决问题的基本步骤为:

  • 确定状态(开一个数组)
    db[i][j]:长度为[0…i]的字符串text1和长度为[0…j]的字符串text2的公共子序列的长度为db[i][j]

  • 确定状态转移方程
    db数组大小为int[n][m],两字符串长度为n-1,m-1
    这里我们把两个字符串的最后一个字符去掉,前面剩下的构成两个子字符串,如果两个子字符串的最长公共子序列已经找到,那么它们的最长公共子序列长度存储在db[n-1][m-1]中,那么加上最后一个字符后原字符串的最长公共子序列为:
    (1)最后两元素相等 text1.charAt(n-1)==text2.charAt(m-1) 所以db[n][m]=db[n-1][m-1]+1
    (2)最后两元素不等 db[n][m]=max{db[n][m-1],db[]n-1[m]}
    综上得到状态转移方程为:
    { d b [ i ] [ j ] = d b [ i − 1 ] [ j − 1 ] + 1 t e x t 1. c h a r A t ( i − 1 ) = t e x t 2. c h a r A t ( j − 1 ) d b [ i ] [ j ] = M a t h . m a x ( d b [ i ] [ j − 1 ] , d b [ i − 1 ] [ j ] ) t e x t 1. c h a r A t ( i − 1 ) ≠ t e x t 2. c h a r A t ( j − 1 ) \left\{ \begin{aligned} db[i][j]&=db[i-1][j-1]+1&text1.charAt(i-1)=text2.charAt(j-1) \\ db[i][j]&=Math.max(db[i][j-1],db[i-1][j]) &text1.charAt(i-1)\not=text2.charAt(j-1) \end{aligned} \right. {db[i][j]db[i][j]=db[i1][j1]+1=Math.max(db[i][j1],db[i1][j])text1.charAt(i1)=text2.charAt(j1)text1.charAt(i1)=text2.charAt(j1)

  • 初始化和边界
    (1)当任意一个字符串为空时,最长公共子序列长度都为零,所以db[0][0…m]和db[0…n][0]都应该初始化为零
    (2)注意db数组和字符串数组的大小,避免数组越界

  • 确定计算顺序
    从状态转移方程可以看出,获取db[i][j]的值有三个方向
    在这里插入图片描述
    所以我们运算的顺序为从左到右,从上到下

代码

public static int LongestCommonSubsequence(String text1,String text2){

        int len1=text1.length(),len2=text2.length();
        //开一个数组
        int [][]db=new int [len1+1][len2+1];

        //初始化
        for(int i=0;i<=len1;i++){
            db[i][0]=0;
        }
        for(int j=0;j<=len2;j++){
            db[0][j]=0;
        }

        for(int i=1;i<=len1;i++){
            for(int
             j=1;j<=len2;j++){
                if(text1.charAt(i-1)==text2.charAt(j-1)){
                    db[i][j]=db[i-1][j-1]+1;
                }
                else{
                    db[i][j]=Math.max(db[i][j-1],db[i-1][j]);
                }
            }
        }
        return db[len1][len2];
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值