动态规划解决最长公共子序列,动态规划最长公共子序列问题

  动态规划解决最长公共子序列,动态规划最长公共子序列问题

  描述给定str1和str2的两个字符串的最长公共子序列。如果最长公共子序列为空,则返回“-1”。目前,在给定的数据中只有一个最长的公共子序列。

  数据范围:需求:空间复杂度,时间复杂度

  示例1输入:

  1A2C3D4B56 , B1D23A456A 返回值:

  123456 示例2输入:

  Abc , def 返回值:

  -1 示例3输入:

  Abc , abc 返回值:

  “Abc”示例4输入:

  Ab ,返回值:

  “-1”问题需要最长的公共子序列,因此所有字母相同且方向递增的字母都可以包含在统计中。另外,因为要返回最长的序列,所以不仅要问最长序列的长度,还要记录动态规划的路径。

  动态规划递归的实现思想如下:

  动态规划问题,总是逃不出以下几个步骤:

  确定dp数组表示的意义:假设s1和s2的长度分别为m和n,我们用数组dp[i][k]表示s1的前I个字符和s2的前k个字符的最长公共长度,用m[i][k]记录每个选择的方向来确定初始条件:dp[0][i],dp[i][0]都为0。那么dp[i][k]=dp[i-1][k-1] 1。此时设m[i][k]=1,表示从s1[i-1]和s2[k-1]子串递归如果s1[i]!=s2[k],则dp[i][k]等于dp[i-1][k]或dp[i][k-1]中的一个。当m[i][k]取2时,表示来自s1[i-1] s2[k],取3表示来自S1 [

  传递参数时,尽量使用引用,减少不必要的计算。比如用边界条件提前返回,否则不给内存和时间~ ~其实上面的路径记录表M可以省略,因为我们可以通过dp[i][k]和dp[i][k-1]的大小关系判断路径方向码如下:

  #包含位/标准数据。h

  //动态编程问题,总是逃不出以下几个步骤:

  //1.确定dp数组所表示的意义:假设s1和s2的长度分别为m和n,我们用arr[i][k]数组来表示s1的前I个字符和s2的前k个字符的最长公共长度。

  //2.确定初始条件:arr[0][i]和arr[i][0]的值都是0。

  //3.确定递归关系:

  //1.如果s1[i]==s2[k],那么arr[i][k]=arr[i-1][k-1] 1

  //2.如果s1[i]!=s2[k],则arr[i][k]等于arr[i-1][k]或arr[i][k-1]。

  //4.arr[m][n]是最长子序列的长度。

  //5.但是题目要求返回最长序列的内容,所以我们需要另外一个表格来记录我们在推导过程中的方向选择。

  //1.我们使用表[i][k]来指示在上一步中到达当前时间时的方向选择。

  //2.如果s1[i]==s2[k],则表示应该将s1[i]添加到最长的序列中。

  //3.如果s1[i]!=s2[k],那么最长的自夸应该产生在s1[i-1],s2[k]或者s1[i],s2[k-1],

  //这个问题可以通过递归来解决

  //注:对于arr[i][k],我们在思考问题的时候,应该认为arr小于I和k的所有值都是已知的。

  std:string walk(std:string s1,std:string s2,int i,int k,std:vector std:vector int m)

  {

  如果(i==0 k==0)

  {

  返回“”;

  }

  如果(m[i][k]==1)

  {

  回程步行(s1,s2,i - 1,k - 1,m)。append(1,S1[I-1]);

  }

  如果(m[i][k]==2)

  {

  回程步行(s1,s2,i - 1,k,m);

  }

  回程步行(s1,s2,I,k - 1,m);

  }

  标准:字符串LCS(标准:字符串s1,标准:字符串s2)

  {

  if (s1.empty() s2.empty())

  {

  return -1 ;

  }

  STD:vector STD:vector int DP(S1 . size()1,std:vector int (s2.size() 1,0));

  STD:vector STD:vector int m(S1 . size()1,std:vector int (s2.size() 1,0));

  for(int I=1;I=S1 . size();我)

  {

  for(int k=1;k=S2 . size();k)

  {

  if (s1[i - 1]==s2[k - 1])

  {

  DP[I][k]=DP[I-1][k-1]1;

  m[I][k]=1;

  }

  其他

  {

  if (dp[i - 1][k] dp[i][k - 1])

  {

  DP[I][k]=DP[I-1][k];

  m[I][k]=2;

  }

  其他

  {

  DP[I][k]=DP[I][k-1];

  m[I][k]=3;

  }

  }

  }

  }

  STD:string ans { -1 };

  if (dp[s1.size()][s2.size()]!=0)

  {

  ans=walk(s1,s2,s1.size(),s2.size(),m);

  }

  返回ans

  }动态规划栈的实现以下代码由Niuke.com官方提供。

  类别解决方案{

  公共:

  字符串LCS(字符串s1,字符串s2) {

  //只要有空字符串,就没有子序列

  if(S1 . length()==0 S2 . length()==0)

  return -1 ;

  int len 1=S1 . length();

  int len 2=S2 . length();

  //dp[i][j]表示从第一个字符串到第I位和第二个字符串到第j位的最长公共子序列长度。

  向量向量int dp(len1 1,向量int (len2 1,0));

  //遍历两个字符串每个位置的最长长度

  for(int I=1;i=len1i ){

  for(int j=1;j=len2j ){

  //遇到两个相等的字符

  if(s1[i - 1]==s2[j -1])

  //从左上角开始

  DP[I][j]=DP[I-1][j-1]1;

  //遇到的两个字符不同

  其他

  //从左侧或顶部开始的最大值

  dp[i][j]=max(dp[i - 1][j],DP[I][j-1]);

  }

  }

  //从动态编程数组的末尾开始

  int i=len1,j=len2

  堆栈字符;

  while(dp[i][j]){

  //从左侧方向

  if(dp[i][j]==dp[i - 1][j])

  I-;

  //从上方

  else if(dp[i][j]==dp[i][j - 1])

  j-;

  //从左上方向

  else if(dp[i][j] dp[i - 1][j - 1]){

  I-;

  j-;

  //只有左上方向是字符相等的情况。将它们堆叠起来,以相反的顺序使用。

  s . push(S1[I]);

  }

  }

  string RES=“”;

  //拼接子序列

  而(!s.empty()){

  RES=s . top();

  s . pop();

  }

  //如果两者完全不同,并且返回字符串为空,则将其更改为-1

  返回res!= ?RES:“-1”;

  }

  };

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • office2010激活密钥大全 怎么永久激活office2010
  • project2010产品密钥免费_project2010激活密钥永久激活码
  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • chatgpt是什么?为什么这么火?
  • ChatGPT为什么注册不了?OpenAI ChatGPT的账号哪里可以注册?
  • OpenAI ChatGPT怎么注册账号?ChatGPT账号注册教程
  • chatgpt什么意思,什么是ChatGPT ?
  • CAD中怎么复制图形标注尺寸不变,CAD中怎么复制图形线性不变
  • cad中怎么创建并使用脚本文件,cad怎么运行脚本
  • cad中快速计算器的功能,cad怎么快速计算
  • cad中快速修改单位的方法有哪些,cad中快速修改单位的方法是
  • cad中心点画椭圆怎么做,cad轴测图怎么画椭圆
  • CAD中常用的快捷键,cad各种快捷键的用法
  • 留言与评论(共有 条评论)
       
    验证码: