找出X={x1,x2,x,3,x4,x5…….} Y={y1,y2,y3,y4……}最长公共子序列

    2个序列的最长公共子序列包含了这2个序列的前缀的最长公共子序列。因此,最长公共子序列问题具有最优子结构性质。
    由最优子结构性质可建立递归关系如下:
    image.png

    Screenshot_20220322_234851.jpg
    Screenshot_20220322_200152_tv.danmaku.bili_edit_581003621199813.jpg

    1. void LSCLengh(int m, int n, char x[], char y[]) {
    2. //m是x数组长度
    3. //n是y数组长度
    4. //c[m+1][n+1]数组是辅助空间,记录
    5. //b[m+1][n+1]数组记录 1-LeftUp、2-UP、3-Left
    6. int i, j;
    7. for (i = 0; i <= m; i++)
    8. c[i][0] = 0;
    9. for (i = 1; i <= n; i++)
    10. c[0][i] = 0;//边缘初始化
    11. for (i = 1; i <= m; i++) {
    12. for (j = 1; j <= n; j++)
    13. {
    14. if (x[i] == y[j])
    15. {
    16. c[i][j] = c[i - 1][j - 1]+1;
    17. b[i][j] = 1;
    18. }
    19. else if(c[i-1][j]>=c[i][j-1])
    20. {
    21. c[i][j] = c[i - 1][j];
    22. b[i][j] = 2;
    23. }
    24. else
    25. {
    26. c[i][j] = c[i][j - 1];
    27. b[i][j] = 3;
    28. }
    29. }
    30. }
    31. }
    32. //构造最长公共子序列
    33. void lcs(int i, int j, char x[])
    34. {
    35. if (i == 0 || j == 0)
    36. return;
    37. if (b[i][j] == 1)
    38. {
    39. lcs(i - 1, j - 1, x);
    40. cout << x[i];
    41. }
    42. else if (b[i][j] == 2)
    43. lcs(i - 1, j, x);
    44. else
    45. lcs(i, j - 1, x);
    46. }

    时间复杂度:O(mn)
    在算法lcsLength和lcs中,可进一步将数组b省去。事实上,数组元素c[i][j]的值仅由c[i-1][j-1]c[i-1][j]c[i][j-1]这3个数组元素的值所确定。对于给定的数组元素c[i][j],可以不借助于数组b而仅借助于c本身在时间内确定c[i][j]的值是由c[i-1][j-1],c[i-1][j]和c[i][j-1]中哪一个值所确定的。
    如果只需要计算最长公共子序列的长度,则算法的空间需求可大大减少。事实上,在计算c[i][j]时,只用到数组c的第i行和第i-1行。因此,用2行的数组空间就可以计算出最长公共子序列的长度。进一步的分析还可将空间需求减至O(min(m,n))

    1. #include<iostream>
    2. using namespace std;
    3. int c[7 + 1][6 + 1];
    4. int b[7 + 1][6 + 1];
    5. void LSCLengh(int m, int n, char x[], char y[]) {
    6. //m是x数组长度
    7. //n是y数组长度
    8. //c[m+1][n+1]数组是辅助空间,记录
    9. //b[m+1][n+1]数组记录 1-LeftUp、2-UP、3-Left
    10. int i, j;
    11. for (i = 0; i <= m; i++)
    12. c[i][0] = 0;
    13. for (i = 1; i <= n; i++)
    14. c[0][i] = 0;//边缘初始化
    15. for (i = 1; i <= m; i++) {
    16. for (j = 1; j <= n; j++)
    17. {
    18. if (x[i] == y[j])
    19. {
    20. c[i][j] = c[i - 1][j - 1]+1;
    21. b[i][j] = 1;
    22. }
    23. else if(c[i-1][j]>=c[i][j-1])
    24. {
    25. c[i][j] = c[i - 1][j];
    26. b[i][j] = 2;
    27. }
    28. else
    29. {
    30. c[i][j] = c[i][j - 1];
    31. b[i][j] = 3;
    32. }
    33. }
    34. }
    35. cout << endl;
    36. for (i = 1; i <= m; i++) {
    37. cout << " ";
    38. for (j = 1; j <= n; j++)
    39. cout << c[i][j] << " ";
    40. cout << endl;
    41. }
    42. cout << endl;
    43. for (i = 1; i <= m; i++) {
    44. cout << " ";
    45. for (j = 1; j <= n; j++)
    46. cout << b[i][j] << " ";
    47. cout << endl;
    48. }
    49. }
    50. //构造最长公共子序列
    51. void lcs(int i, int j, char x[])
    52. {
    53. if (i == 0 || j == 0)
    54. return;
    55. if (b[i][j] == 1)
    56. {
    57. lcs(i - 1, j - 1, x);
    58. cout << x[i];
    59. }
    60. else if (b[i][j] == 2)
    61. lcs(i - 1, j, x);
    62. else
    63. lcs(i, j - 1, x);
    64. }
    65. int main() {
    66. char x[] = {' ', 'A','B','C','B','D','A','B'};
    67. char y[] = {' ' ,'B','D','C','A','B','A' };
    68. LSCLengh(7, 6, x, y);
    69. lcs(7, 6, x);
    70. return 0;
    71. }

    运行结果:
    image.png