目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • java语言版本
    • c语言版本
    • c++语言版本
  • 思考感悟
  • 写在最后

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定两个字符串str1和str2,求两个字符串的最长公共子序列
如:
str1:1A2C3D4B56
str2:B1D23CA45B6A
结果为:
12C4B6 或 123456

解决方案

原问题
动态规划方法:
1、构造动态规划矩阵,dp[i][j] 代表str1[0…i]和str2[0…j]之间的最长公共子序列的长度
2、递归关系:
· 比较dp[i-1][j]和dp[i][j-1]的值,如果不相同,则找大的赋值给dp[i][j],如果相同,则比较str1[i]和str2[j]是否相同,如果相同则dp[i][j] = dp[i-1][j] + 1;

代码编写

java语言版本

原问题:
动态规划方法:

    /*** 获取dp矩阵* @return*/public static int[][] getDpCP(String str1, String str2) {if (str1 == null || str1.length() == 0|| str2 == null || str2.length() == 0) {return null;}char[] chars1 = str1.toCharArray();char[] chars2 = str2.toCharArray();int[][] dp = new int[chars1.length][chars2.length];dp[0][0] = chars1[0] == chars2[0] ? 1 : 0;// 初始化for (int i = 1; i < dp.length; i++) {dp[i][0] = dp[i-1][0] == 1 || chars2[0] == chars1[i] ? 1 : 0;}for (int i = 1; i < dp[0].length; i++) {dp[0][i] = dp[0][i-1] == 1 || chars1[0] == chars2[i] ? 1 : 0;}for (int i = 1; i < dp.length; i++) {for (int j = 1; j < dp[0].length; j++) {if (dp[i-1][j] == dp[i][j-1]) {dp[i][j] = chars1[i] == chars2[j] ? dp[i-1][j] + 1 : dp[i-1][j];}else {dp[i][j] = dp[i-1][j] > dp[i][j-1] ? dp[i-1][j] : dp[i][j-1];}}}return dp;}/*** 根据dp获取序列* @param str1* @param str2* @return*/public static String getSeqCP(String str1, String str2) {if (str1 == null || str1.length() == 0|| str2 == null || str2.length() == 0) {return null;}char[] chars1 = str1.toCharArray();char[] chars2 = str2.toCharArray();int[][] dpCP = getDpCP(str1, str2);int maxLen = chars1.length > chars2.length ? chars1.length : chars2.length;char[] charRes = new char[maxLen];int index = 0;int i = dpCP.length-1;int j = dpCP[0].length-1;while (i != 0 && j != 0) {if (dpCP[i-1][j] == dpCP[i][j-1] && dpCP[i-1][j] == dpCP[i][j] - 1) {// 添加当前值charRes[index++] = chars1[i];i--;}else if (dpCP[i-1][j] >= dpCP[i][j-1]){i--;}else {j--;}}if (dpCP[i][j] == 1) {charRes[index++] = i == 0 ? chars1[i] : chars2[j];}// 翻转CommonUtils.reverseChar(charRes, 0, index);return String.valueOf(charRes, 0, index);}public static void main(String[] args) {System.out.println(getSeqCP("1A2C3D4B56", "B1D23CA45B6A"));}

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

首先dp[i][j]的含义是非常容易想到的吧,就算是递归方法,无非入参就是str1和str2,i,j,四个变量,这里没有使用暴力递归了,因为实在是太消耗没用的资源了,所以我们把它淘汰了!
第二个要素就是递推公式的由来,这里我第二遍做这个题,时隔半年,最后还是想到了,首先dp[i-1][j]代表str1[0…i-1]和str2[0…j]之间的最长子序列长度,dp[i][j-1]就不用说了,那么如果两个值相等说明 有没有str1[i] ,str2[j]都无所谓,也间接说明那两个状态中的最长子序列不包含当前值,那么如果当前str1[i] = str2[j]刚好dp[i][j] 状态能够将最长子序列拓展一个值。 那么如果str1[i] != str2[j]不相等就仍然继承原来的两个状态。
dp[i-1][j] != dp[i][j-1] 的情况是什么呢?我这里认为,如果不相等说明这两个状态跟str1[i] 和str2[j] 有关系,去掉某个值的时候影响了最长子序列,那么这个时候不管str1[i] 与str2[j]是否相等,dp[i][j] 都只能继承到前面两个状态中较大的那个,这个要细品一下,才能理解。

最后说一下如何求子序列,当我们求得最长子序列长度dp之后,如果理解了dp矩阵的求解过程和原理之后,倒回来求序列就比较好理解了,
从dp最后一个状态开始,当前面的和上面的两个状态,也就是dp[i-1][j] 和 dp[i][j-1]相等的时候判断当前dp状态是否是前面两个状态+1,如果是的,那么说明当前值是 被选入最长子序列的,如果没有+1,说明当前值没有被选入,那么走较大的(相等时走哪个都可以),如果dp[i-1][j] 和 dp[i][j-1]不相等,那么走较大的,不选入任何子序列。
为什么结果中会有两种答案呢?
就是因为dp[i-1][j] 和 dp[i][j-1]相等的时候可以有两种选择,如果你选择了其中一种就会得到一种答案,另一种就会得到另一种答案。

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!

【算法】【递归与动态规划模块】两个字符串的公共最长子序列相关推荐

  1. python两个字符串查找公共字符串

    两个字符串查找公共字符串,要最大最长公共字符串,去判断target列表中元素长度即可. re模块中finditer的简单实例 import re def common_str(str1,str2):# ...

  2. 打印两个字符串的公共字符

    输入两个字符串,打印两个字符串中公共的字符,如果没有公共字符打印 公共字符不存在 例如:字符串1为 abc123 , 字符串2为 huak3 , 打印 a3 str_1 = input() str_2 ...

  3. 【算法】【递归与动态规划模块】两个字符串的最长公共子数组

    目录 前言 问题介绍 解决方案 代码编写 java语言版本 c语言版本 c++语言版本 思考感悟 写在最后 前言 当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批 ...

  4. 【算法】【递归与动态规划模块】斐波那契数列的系列问题解法及递推类型问题的最优解

    目录 前言 问题介绍 解决方案 代码编写 java语言版本 c语言版本 c++语言版本 思考感悟 写在最后 前言 当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批 ...

  5. 动态规划之两个字符串的最大子序列

    1.问题 求两个字符串的最大子序列 1).子序列和子字符串有区别,子字符串(子串)必须连续,列如 s1 = "ABCDAB"  s2= "BBCDAAB" s1 ...

  6. 找到两个字符串的公共字符,并按照其中一个的排序

    题目:写一函数f(a,b),它带有两个字符串参数并返回一串字符,该字符串只包含在两个串中都有的并按照在a中的顺序.写一个版本算法复杂度O(N^2)和一个O(N) . O(N^2): 对于a中的每个字符 ...

  7. 递归和动态规划的一个区别(递归是自顶向下,然后返回计算;动态规划是自低向上运算)

    1看到介绍递归比较好的文章,链接如下: https://blog.csdn.net/sinat_38052999/article/details/73303111 参考自:https://www.do ...

  8. 字谜大全及答案100个_检查字谜(检查两个字符串是否是字谜)

    字谜大全及答案100个 Problem statement: Given two strings, check whether two given strings are anagram of eac ...

  9. Python Levenshtein(两个文本比较,两个字符串比较)

    安装: pip3 install python-Levenshtein==0.12.0 实例一: #! /usr/bin/python # -*- coding: utf8 -*- # @Time : ...

最新文章

  1. DSVS7050签名服务器的网站,吉大正元数字签名服务器-安装部署手册(COM版 VCTK_S接口)2.1.1.doc...
  2. iTOP-4412开发板驱动lcd显卡以及linux开机log的修改方法
  3. 浅谈三级分销系统开发对企业的作用
  4. ML之LiR:基于编程实现简单线性回归案例
  5. jmeter的性能监控框架搭建记录(Influxdb+Grafana+Jmeter)
  6. java文件传输连接方式_Java 学习笔记 网络编程 使用Socket传输文件 CS模式
  7. QGraphicsView,QGraphicsScene,QGraphicsItem
  8. ExtFrame的特点与缺点
  9. JavaScript HTML DOM 元素(节点)
  10. [互联网面试笔试汇总C/C++-9] 实现赋值运算符函数-剑指offer
  11. linux 解决Linux上解压jdk报错gzip: stdin: not in gzip format
  12. OpenMP4.0: #pragma openmp simd实现SIMD指令优化(ARM,X86,MIPS)
  13. 多元统计分析最短距离法_多元统计分析方法 -
  14. 任意多边形的最大内切圆算法
  15. 地坤诀中所记录的第二元婴的炼制办法与其余的炼制方式不一样
  16. 交互体验设计优秀的产品
  17. 木门企业最典型的十八个问题
  18. Android studio 设置背景图
  19. 微信小程序接收二进制流文件(图片预览,文件打开)
  20. win7笔记本外接显示器html,window7笔记本外接显示器只显示一个屏幕怎么设置

热门文章

  1. 绿盟科技应急响应中心安全研究员邓永凯:那些年,你怎么写总会出现的漏洞...
  2. 向日葵族群的典型特征
  3. 关于StringUtils的各种方法的功能、解析
  4. c语言中 %d与%2d与%02d的区别在哪里
  5. 经常生气的人,身体有什么变化?
  6. iphone11的计算机在哪,iPhone11怎么连接电脑?iPhone11信任并连接电脑图文教程
  7. WLAN驱动分析文档_gzc126_新浪博客
  8. 2021四川高考成绩等位分查询,2021年四川高考位次排名查询,四川高考位次所对应的学校...
  9. C语言中的while的意思,C语言中while是什么意思
  10. 如何从T-SNE或Umap中找到你想要的点?