快捷搜索:  汽车  科技

序列型动态规划(动态规划基础篇之最长公共子序列问题)

序列型动态规划(动态规划基础篇之最长公共子序列问题)对序列 1 3 5 4 2 6 8 7和序列 1 4 8 6 7 5 来说例如:对于一个长度为n的序列,它一共有2^n 个子序列,有(2^n – 1)个非空子序列。请注意:子序列不是子集,它和原始序列的元素顺序是相关的。(2)公共子序列 : 顾名思义,如果序列C既是序列A的子序列,同时也是序列B的子序列,则称它为序列A和序列B的公共子序列。

一些概念:

(1)子序列: 一个序列A = a1 a2 ……an 中任意删除若干项,剩余的序列叫做A的一个子序列。也可以认为是从序列A按原顺序保留任意若干项得到的序列。

例如:

对序列 1 3 5 4 2 6 8 7来说,序列3 4 8 7 是它的一个子序列。

对于一个长度为n的序列,它一共有2^n 个子序列,有(2^n – 1)个非空子序列。

请注意:子序列不是子集,它和原始序列的元素顺序是相关的。

(2)公共子序列 : 顾名思义,如果序列C既是序列A的子序列,同时也是序列B的子序列,则称它为序列A和序列B的公共子序列。

例如:

对序列 1 3 5 4 2 6 8 7和序列 1 4 8 6 7 5 来说

序列1 8 7是它们的一个公共子序列。

请注意: 空序列是任何两个序列的公共子序列。

例如: 序列1 2 3和序列4 5 6的公共子序列只有空序列。

(3)最长公共子序列

A和B的公共子序列中长度最长的(包含元素最多的)叫做A和B的公共子序列。

另外,说一下复杂度?

时间复杂度时O(n * m),空间也是O(n * m)

今天对LCS的讲解就到这里,聪明的你是不是已经蠢蠢欲动要AC问题啦? 心动不如行动,赶快吧。

在这里,本宝宝找到了两个模板,先收藏着,等过段在细细琢磨琢磨,有新的收获再补充。

代码一是让你输入两个序列,然后输出最长公共子序列和长度。

代码二是让你输入三个序列,然后输出最长公共子序列的长度。

代码一:


  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. int LCSLength(char* str1 char* str2 int **b)
  5. {
  6. int i j length1 length2 len;
  7. length1 = strlen(str1);
  8. length2 = strlen(str2);
  9. //双指针的方法申请动态二维数组
  10. int **c = new int*[length1 1]; //共有length1 1行
  11. for(i = 0; i < length1 1; i )
  12. c[i] = new int[length2 1];//共有length2 1列
  13. for(i = 0; i < length1 1; i )
  14. c[i][0]=0; //第0列都初始化为0
  15. for(j = 0; j < length2 1; j )
  16. c[0][j]=0; //第0行都初始化为0
  17. for(i = 1; i < length1 1; i )
  18. {
  19. for(j = 1; j < length2 1; j )
  20. {
  21. if(str1[i-1]==str2[j-1])//由于c[][]的0行0列没有使用,c[][]的第i行元素对应str1的第i-1个元素
  22. {
  23. c[i][j]=c[i-1][j-1] 1;
  24. b[i][j]=0; //输出公共子串时的搜索方向
  25. }
  26. else if(c[i-1][j]>c[i][j-1])
  27. {
  28. c[i][j]=c[i-1][j];
  29. b[i][j]=1;
  30. }
  31. else
  32. {
  33. c[i][j]=c[i][j-1];
  34. b[i][j]=-1;
  35. }
  36. }
  37. }
  38. /*
  39. for(i= 0; i < length1 1; i )
  40. {
  41. for(j = 0; j < length2 1; j )
  42. printf("%d " c[i][j]);
  43. printf("\n");
  44. }
  45. */
  46. len=c[length1][length2];
  47. for(i = 0; i < length1 1; i ) //释放动态申请的二维数组
  48. delete[] c[i];
  49. delete[] c;
  50. return len;
  51. }
  52. void PrintLCS(int **b char *str1 int i int j)
  53. {
  54. if(i==0 || j==0)
  55. return ;
  56. if(b[i][j]==0)
  57. {
  58. PrintLCS(b str1 i-1 j-1);//从后面开始递归,所以要先递归到子串的前面,然后从前往后开始输出子串
  59. printf("%c" str1[i-1]);//c[][]的第i行元素对应str1的第i-1个元素
  60. }
  61. else if(b[i][j]==1)
  62. PrintLCS(b str1 i-1 j);
  63. else
  64. PrintLCS(b str1 i j-1);
  65. }
  66. int main(void)
  67. {
  68. char str1[100] str2[100];
  69. int i length1 length2 len;
  70. printf("请输入第一个字符串:");
  71. gets(str1);
  72. printf("请输入第二个字符串:");
  73. gets(str2);
  74. length1 = strlen(str1);
  75. length2 = strlen(str2);
  76. //双指针的方法申请动态二维数组
  77. int **b = new int*[length1 1];
  78. for(i= 0; i < length1 1; i )
  79. b[i] = new int[length2 1];
  80. len=LCSLength(str1 str2 b);
  81. printf("最长公共子序列的长度为:%d\n" len);
  82. printf("最长公共子序列为:");
  83. PrintLCS(b str1 length1 length2);
  84. printf("\n");
  85. for(i = 0; i < length1 1; i )//释放动态申请的二维数组
  86. delete[] b[i];
  87. delete[] b;
  88. system("pause");
  89. return 0;
  90. }

代码二:


  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. int max1(int m int n)
  5. {
  6. if(m>n)
  7. return m;
  8. else
  9. return n;
  10. }
  11. int max2(int x int y int z int k int m int n)
  12. {
  13. int max=-1;
  14. if(x>max)
  15. max=x;
  16. if(y>max)
  17. max=y;
  18. if(z>max)
  19. max=z;
  20. if(k>max)
  21. max=k;
  22. if(m>max)
  23. max=m;
  24. if(n>max)
  25. max=n;
  26. return max;
  27. }
  28. int LCSLength(char* str1 char* str2 char* str3) //求得三个字符串的最大公共子序列长度并输出公共子序列
  29. {
  30. int i j k length1 length2 length3 len;
  31. length1 = strlen(str1);
  32. length2 = strlen(str2);
  33. length3 = strlen(str3);
  34. //申请动态三维数组
  35. int ***c = new int**[length1 1]; //共有length1 1行
  36. for(i = 0; i < length1 1; i )
  37. {
  38. c[i] = new int*[length2 1]; //共有length2 1列
  39. for(j = 0; j<length2 1; j )
  40. c[i][j] = new int[length3 1];
  41. }
  42. for(i = 0; i < length1 1; i )
  43. {
  44. for(j = 0; j < length2 1; j )
  45. c[i][j][0]=0;
  46. }
  47. for(i = 0; i < length2 1; i )
  48. {
  49. for(j = 0; j < length3 1; j )
  50. c[0][i][j]=0;
  51. }
  52. for(i = 0; i < length1 1; i )
  53. {
  54. for(j = 0; j < length3 1; j )
  55. c[i][0][j]=0;
  56. }
  57. for(i = 1; i < length1 1; i )
  58. {
  59. for(j = 1; j < length2 1; j )
  60. {
  61. for(k = 1; k < length3 1; k )
  62. {
  63. if(str1[i-1]==str2[j-1] && str2[j-1]==str3[k-1])
  64. c[i][j][k]=c[i-1][j-1][k-1] 1;
  65. else if(str1[i-1]==str2[j-1] && str1[i-1]!=str3[k-1])
  66. c[i][j][k]=max1(c[i][j][k-1] c[i-1][j-1][k]);
  67. else if(str1[i-1]==str3[k-1] && str1[i-1]!=str2[j-1])
  68. c[i][j][k]=max1(c[i][j-1][k] c[i-1][j][k-1]);
  69. else if(str2[j-1]==str3[k-1] && str1[i-1]!=str2[j-1])
  70. c[i][j][k]=max1(c[i-1][j][k] c[i][j-1][k-1]);
  71. else
  72. {
  73. c[i][j][k]=max2(c[i-1][j][k] c[i][j-1][k] c[i][j][k-1] c[i-1][j-1][k] c[i-1][j][k-1] c[i][j-1][k-1]);
  74. }
  75. }
  76. }
  77. }
  78. len=c[length1][length2][length3];
  79. for(i = 1; i < length1 1; i ) //释放动态申请的三维数组
  80. {
  81. for(j = 1; j < length2 1; j )
  82. delete[] c[i][j];
  83. delete[] c[i];
  84. }
  85. delete[] c;
  86. return len;
  87. }
  88. int main(void)
  89. {
  90. char str1[100] str2[100] str3[100];
  91. int len;
  92. printf("请输入第一个字符串:");
  93. gets(str1);
  94. printf("请输入第二个字符串:");
  95. gets(str2);
  96. printf("请输入第三个字符串:");
  97. gets(str3);
  98. len=LCSLength(str1 str2 str3);
  99. printf("最长公共子序列的长度为:%d\n" len);
  100. system("pause");
  101. return 0;
  102. }

序列型动态规划(动态规划基础篇之最长公共子序列问题)(1)

猜您喜欢: