动态规划之最长公共子序列&最长公共子串

2人阅读 评论(0) 收藏 举报
分类:

题目  动态规划之最长公共子序列&最长公共子串

  如果字符串1的所有字符按其在字符串中的顺序出现在另外一个字符串2中,则字符串1称之为字符串2的子序列。

  注意,并不要求子子序列(字符串1)的字符必须连续出现在字符串2中。

  请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子序列。


最长公共子序列

https://www.nowcoder.com/practice/c996bbb77dd447d681ec6907ccfb488a?tpId=49&tqId=29348&tPage=1&rp=1&ru=/ta/2016test&qru=/ta/2016test/question-ranking

  例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子序列,则输出它们的长度4,并打印任意一个子序列。

分析

  本问题是典型的动态规划问题,子字符串的最优解为字符串提供了决策依据。有两个字符串str1和str2,设c[i,j]为子串str1[0-i]和str2[0-j]的最长公共子序列的长度,

  如果str1[i]=str2[j],则c[i,j]=c[i-1,j-1]+1;

  如果str1[i]!=str2[j],则c[i,j]要么等于str1[0,i-1]和str2[0,j]的最长公共子序列的长度,要么等于str1[0,i]和str2[0,j-1]的最长公共子序列的长度,取两者的最大值即是c[i,j]

  如图一个示例

        

  状态转移方程:

  c[0,j]=0;

  c[i,0]=0;

  c[i,j]=c[i-1,j-1]+1, 若str1[i]=str2[j];

  c[i,j]=max{c[i-1,j],c[i,j-1]}

        子序列最大长度为c[i][j],即矩阵的最后一个元素

代码

复制代码
 1 int Lcslen(char* stra,char* strb,int** c)
 2 {
 3     int len_a=strlen(stra);
 4     int len_b=strlen(strb);
 5 
 6     for(int i=1;i<=len_a;i++)
 7     {
 8         for(int j=1;j<=len_b;j++)
 9         {
10             if(stra[i-1]==strb[j-1])
11             {
12                 c[i][j]=c[i-1][j-1]+1;
13             }else
14             {
15                 c[i][j]=(c[i][j-1]>c[i-1][j])?c[i][j-1]:c[i-1][j];
16             }
17         }
18     }
19 
20     return c[len_a][len_b];
21 }
22 
23 void lcs(char* stra,char* strb)
24 {
25     if(stra==NULL||strb==NULL)
26         return;
27     int len_a=strlen(stra);
28     int len_b=strlen(strb);
29     int** c=new int*[len_a+1];
30     for (int i=0;i<=len_a;i++)
31     {
32         c[i]=  new int[len_b+1]();
33     }
34 
35     int k=Lcslen(stra,strb,c);
36 
37     char* lcs=new char[k];
38 
39     int i=len_a+1;
40     int j=len_b+1;
41     while(k>=0)
42     {
43         if(c[i][j]==c[i][j-1])
44         {
45             j--;
46         }else if(c[i][j]==c[i-1][j])
47         {
48             i--;
49         }else if(c[i][j]==c[i-1][j-1])
50         {
51             lcs[k--]=stra[i-1];
52             i--;
53             j--;
54         }
55     }
56 
57     for (int i=0;i<=len_a;i++)
58     {
59         delete[] c[i]; 
60     }
61     delete[] c;
62 }
复制代码

 

动态规划之最长公共子串


https://www.nowcoder.com/practice/02e7cc263f8a49e8b1e1dc9c116f7602?tpId=49&tqId=29349&tPage=1&rp=1&ru=/ta/2016test&qru=/ta/2016test/question-ranking

  本题和上题的区别是子串要求是连续的。那么当str1[i]!=str2[j]的时候,前面的公共子串到此结束,c[i,j]重新等于0,开始寻找下一个公共子串。

  状态转移方程式变为:

  c[0,j]=0;

  c[i,0]=0;

  c[i,j]=c[i-1,j-1]+1, 若str1[i]==str2[j];

  c[i,j]=0, 若str1[i]!=str2[j]

  最大子串长度max_dis=max{c[i][j]}

代码

复制代码
 1 int ContinuousLCS(char* stra,char* strb)
 2 {
 3     if(stra==NULL||strb==NULL)
 4         return -1;
 5 
 6     int len_a=strlen(stra);
 7     int len_b=strlen(strb);
 8 
 9     //new space of int[][]
10     int** c=new int*[len_a+1];
11     for (int i=0;i<=len_a;i++)
12     {
13         c[i]=  new int[len_b+1]();
14     }
15 
16     int max_dis=0,index=0;
17     for(int i=1;i<=len_a;i++)
18     {
19         for(int j=1;j<=len_b;j++)
20         {
21             if(stra[i-1]==strb[j-1])
22             {
23                 c[i][j]=c[i-1][j-1]+1;
24             }else
25             {
26                 c[i][j]=0;
27             }
28 
29             if (max_dis<=c[i][j])
30             {
31                 max_dis=c[i][j];
32                 index=i;
33             }
34         }
35 
36     }
37 
38     //output result
39     for (int i=index-max_dis;i<index;i++)
40     {
41         cout<<stra[i]<<' ';
42     }
43     cout<<endl;
44 
45     //free
46     for (int i=0;i<=len_a;i++)
47     {
48         delete[] c[i]; 
49     }
50     delete[] c;
51 
52     return max_dis;
53 }
查看评论

Java动态规划 实现最长公共子序列以及最长公共子字符串

动态规划法 经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题。简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加。 ...
  • hanleijun
  • hanleijun
  • 2014-04-15 22:28:24
  • 949

动态规划:求最长公共子串/最长公共子序列

最长公共子序列和最长公共子串区别        最长公共子串(Longest Common Substring)与最长公共子序列(Longest Common Subsequence)的区别: 子串要...
  • u013074465
  • u013074465
  • 2015-04-30 11:30:58
  • 13879

动态规划 最长公共子序列 过程图解

1.基本概念       首先需要科普一下,最长公共子序列(longest common sequence)和最长公共子串(longest common substring)不是一回事儿。什么是子序...
  • hrn1216
  • hrn1216
  • 2016-05-29 22:54:25
  • 53561

javascript写算法(一) 动态规划:最长公共子序列

csdn是疯了吗,是baidu算出来的广告嵌在了iframe里,fixed to viewport,之前一直用的c++写算法,在std的基础上javascript的“人造性”更强,比如数组和字符串都有...
  • github_36487770
  • github_36487770
  • 2017-03-26 22:35:48
  • 983

动态规划——最长公共子序列和最长公共子串之Python实现

  • 2017年10月22日 20:59
  • 2KB
  • 下载

最长公共子序列与最长公共子串(DP)

1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogsbelong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序...
  • u012102306
  • u012102306
  • 2016-11-16 11:14:08
  • 9491

动态规划算法之: 最长公共子串

最长公共子串与最长公共子序列区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。而最长公共子序列则并不要求连续。 其实这是一个序贯决策问题,可以用动态规划来求解。我们采用一个二维...
  • daa20
  • daa20
  • 2016-09-20 15:00:03
  • 309

用动态规划的方法求解两个字符串的最长公共子串

package dynamicprogramming; public class LCS { public static int c[][]; //c[i][j]表示Xi和Yj的LCS长度 ...
  • u010339647
  • u010339647
  • 2015-06-19 15:39:46
  • 574

最长公共子序列,C语言动态规划

  • 2013年01月17日 01:42
  • 3KB
  • 下载

C++求解汉字字符串的最长公共子序列 动态规划

最近,我在网上看了一些动态规划求字符串最长公共子序列的代码,但是无一例外都是处理英文字符串,当处理汉字字符串时,经常会出现乱码或者不正确的情况。 我对代码进行了修改,使用wchar_t类型存储字符串,...
  • sxh850297968
  • sxh850297968
  • 2014-11-08 12:11:12
  • 1106
    个人资料
    等级:
    访问量: 1342
    积分: 50
    排名: 180万+
    文章分类
    文章存档