常用算法思想之动态规划的后缀思想

栏目: 编程工具 · 发布时间: 5年前

内容简介:思路:后缀是指要解决的子问题是原问题的后半部分,如果用字符串类描述,相当于子问题永远都是原问题的后半部分 str[i:]str[i:] 表示从下标i开始,一直到末尾的整个字符串给定两个字符串A:

思路:后缀是指要解决的子问题是原问题的后半部分,如果用字符串类描述,相当于子问题永远都是原问题的后半部分 str[i:]

str[i:] 表示从下标i开始,一直到末尾的整个字符串

示例

给定两个字符串A: HIEROGLYPHOLOGY 和字符串B: MICHAELANGELO ,他们最长公共的子序列为

HIEROGLYPHOLOGY <--> MICHAELANGELO

可以得到最长公共子序列长度为5。分析如下:

  • A、B两个字符串,如果字符串A的第一个字符和B的第一个字符一模一样,那这个字符一定是属于最长子序列的一个,剩余部分为A[1:]和B[1:],且最终结果就是在前一个结果的基础上加上剩余部分最长字串长度即可
  • A、B两个字符串,如果第一个字符不一样,最长公共子序列要么包含A中的第一个字符、要么包含B中的第一个字符、或者是两个都不是。即最长公共字串要么你是 A[1:]和B[0:],要么是A[0:]和B[1:],所以最长公共字串就是 A[1:]和B[0:],A[0:]和B[1:]之间的最大值

最终要计算的结果是 dp(A.length()-1,B.length()-1)。即字符串A和字符串B的最长公共子序列长度。

假设输入的字符串A是 HIE B是 MCHI ,目标就是要计算dp(2,3)

2表示A字符串的最后一个下标,3表示B字符串的最后一个下标

常用算法思想之动态规划的后缀思想

横坐标表示字符串A中参与计算最长公共子序列长度的最后一个字符;纵坐标表示字符串B中参与计算最长公共子序列长度的最后一个字符

  1. 先比较A和B的第一个字符,看不相等,执行不相等的逻辑,所以最大公共子序列要么在A[1:]和B[0:],要么在A[0:]和B[1:],要么在A[1:]和B[1:]
常用算法思想之动态规划的后缀思想

x 表示剩余需要比较的子字符开始的位置

  1. 以 A[1:]和B[0:] 为例,首字母仍然不一样,此时最大公共子序列要么在 A[2:]B[0:]、要么在A[1:]和B[1:]
常用算法思想之动态规划的后缀思想
  • 表示当前图表中没有写这个分支,只看挑选的分支执行路径
  1. 以A[1:]和B[1:]为例,首字母仍然不一样,它的最长字串就是A[1:]B[2:]或者是A[2:]B[1:],考虑到这只是个子串,那最终在计算分别以下标1结尾的字符串A和B的最长公共字串中,需要看前面的结果A[1]B[0]和A[0]B[1]的最大值是那个,因而必须先计算出A[0]b[1]才能确定它的取值
常用算法思想之动态规划的后缀思想
  1. 以A[1:]B[2:]为例,A[1]和B[2]不相等,它需要计算的 最长子序列就是A[1:]B[3:]或者是A[2]B[2],同样的要计算A中以1结尾的字串和B中以2结尾的字串的最大子序列长度,先要看下A[0]B[2]的值
常用算法思想之动态规划的后缀思想
  1. 以A[1:]B[3:]为例,A[1]和B[3]一样,但是需要去计算A[0]B[3]

从上面的分析过程可以看到,要计算对应的位置的值,必须先把它之前的值都准备好,才能继续进行,也就是说,如果之前已经计算过,就可以利用它继续计算,否则只能回过头来再计算一遍,这样也不划算,既然如此,就可以按照从横坐标0开始,一行一行的填充数据。

当A取下标0的时候,就是只有1个字母和整个B字符串去对比,当A取下标1的时候,就是A[0:1]去和B对比,对应的操作顺序如下

常用算法思想之动态规划的后缀思想

显示按照蓝线,然后是绿线最后是黄线,然后计算出值。

public int longestCommonSubsequence(String A, String B) {
        // 特殊情况直接返回
        if(A==null || "".equals(A) || B==null || "".equals(B)){
            return 0;
        }
        int length=0;
        int [][] arr=new int[A.length()+1][B.length()+1];
        //从1开始是因为只要当前有一个是一样的,后面的至少和他保持一致,最长序列不会比它少,如果从0开始,那么需要有额外的逻辑去保证第0行的正确性,而从1开始就可以很好的利用现有的逻辑,不必写过多的冗余代码
        for(int i=1;i<=A.length();i++){
           for(int j=1;j<=B.length();j++){
               if(A.charAt(i-1)==B.charAt(j-1)){
                   arr[i][j]=arr[i-1][j-1]+1;
               }else{
                   arr[i][j]=Math.max(arr[i-1][j],arr[i][j-1]);
               }
               
           }
        }
        return arr[A.length()][B.length()];
        
    }
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C专家编程

C专家编程

[美] Peter Vander Linde / 徐波 / 人民邮电出版社 / 2002-12 / 40.00元

《C专家编程》展示了最优秀的C程序员所使用的编码技巧,并专门开辟了一章对C++的基础知识进行了介绍。 书中对C的历史、语言特性、声明、数组、指针、链接、运行时、内存,以及如何进一步学习C++等问题作了细致的讲解和深入的分析。全书撷取几十几个实例进行讲解,对C程序员具有非常高的实用价值。 这本《C专家编程》可以帮助有一定经验的C程序员成为C编程方面的专家,对于具备相当的C语言基础的程序员......一起来看看 《C专家编程》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试