LCS(最长公共子串)系列问题

绝地灬酷狼 2022-05-08 03:58 268阅读 0赞

问题一

探索递归模式下,电脑最长计算的长度情况。(我也很神秘,为什么老师要出这种问题。。。)

就是不断修改下面的n,来看看数值就知道了~

  1. #include <iostream>
  2. using namespace std;
  3. #include <string>
  4. string multiply(string s, int time) {
  5. string t;
  6. for (int i = 0; i < time; ++i) t = t + s;
  7. return t;
  8. }
  9. string x, y;
  10. int lcs(int i, int j) {
  11. if (i == 0 || j == 0) return 0;
  12. if (x[i] == y[j]) return lcs(i - 1, j - 1) + 1;
  13. int temp1 = lcs(i - 1, j);
  14. int temp2 = lcs(i, j - 1);
  15. if (temp1 > temp2) return temp1;
  16. return temp2;
  17. }
  18. int main() {
  19. x = "123";
  20. y = "12";
  21. int n = 16;
  22. x = multiply(x, n);
  23. y = multiply(y, n);
  24. cout << lcs(x.length(), y.length()) << endl;
  25. system("pause");
  26. }

递推实现,并输出路径

  1. #include <iostream>
  2. using namespace std;
  3. #include <string>
  4. int lcs(string A, string B, string &C, int n, int m) {
  5. int i, j, k;
  6. int **L = new int*[n + 1];
  7. for (i = 0; i <= n; ++i) L[i] = new int[m + 1];
  8. int **S = new int*[n + 1];
  9. for (i = 0; i <= n; ++i) S[i] = new int[m + 1];
  10. for (i = 0; i <= n; ++i) L[i][0] = 0;
  11. for (j = 0; j <= m; ++j) L[0][j] = 0;
  12. for (i = 1; i <= n; ++i) {
  13. for (j = 1; j <= m; ++j) {
  14. if (A[i-1] == B[j-1]) {
  15. L[i][j] = L[i - 1][j - 1] + 1;
  16. S[i][j] = 1;
  17. }
  18. else if (L[i - 1][j] >= L[i][j - 1]) {
  19. L[i][j] = L[i - 1][j];
  20. S[i][j] = 2;
  21. }
  22. else {
  23. L[i][j] = L[i][j - 1];
  24. S[i][j] = 3;
  25. }
  26. }
  27. }
  28. k = L[n][m];
  29. C = "";
  30. for (i = 0; i < k; ++i) C.append("0");
  31. i = n, j = m;
  32. while (i != 0 && j != 0) {
  33. switch (S[i][j])
  34. {
  35. case 1:
  36. C[k-1] = A[i-1]; i--; j--; k--; break;
  37. case 2:
  38. i--; break;
  39. case 3:
  40. j--; break;
  41. }
  42. }
  43. int ans = L[n][m];
  44. for (i = 0; i <= n; ++i) delete L[i];
  45. delete[] L;
  46. for (i = 0; i <= n; ++i) delete S[i];
  47. delete[] S;
  48. return ans;
  49. }
  50. int main() {
  51. string X = "bcdbadce", Y = "cabdcbc", Z="";
  52. cout << lcs(X, Y, Z, X.length(), Y.length()) << endl;
  53. cout << Z << endl;
  54. system("pause");
  55. }

输出:

  1. 4
  2. bcbc

思路其实很简单,按照之前做的划分方式就好了。

难点: 在于为什么写为A[i-1] = = B[i-1] 还有就是后面有一个C[k-1] = A[i-1];

解释: 因为全局的i , j都是表示的前面还有多个剩余串数量,也就是是index +1 所以这里定位回去到index的时候,就需要减一了。

问题三

递归式的,但是要求输出序列。

  1. #include <iostream>
  2. using namespace std;
  3. #include <string>
  4. typedef pair<string, int> DATA;
  5. string X = "bcdbadce", Y = "cabdcbc";
  6. DATA lcs(int i, int j) {
  7. if (i == 0 || j == 0) return { "", 0};
  8. if (X[i-1] == Y[j-1]) {
  9. DATA temp = lcs(i - 1, j - 1);
  10. temp.first.push_back(X[i-1]);
  11. temp.second++;
  12. return temp;
  13. }
  14. DATA temp1 = lcs(i - 1, j);
  15. DATA temp2 = lcs(i, j - 1);
  16. if (temp1.second >= temp2.second) return temp1;
  17. return temp2;
  18. }
  19. int main() {
  20. DATA temp = lcs(X.length(), Y.length());
  21. cout << temp.first << "\n" << temp.second << endl;
  22. system("pause");
  23. }

输出为:

  1. bcbc
  2. 4

发表评论

表情:
评论列表 (有 0 条评论,268人围观)

还没有评论,来说两句吧...

相关阅读

    相关 公共序列LCS问题

    好久没有写博客了,刚才在网上看了清华大学的数据结构公开课,链接:https://www.xuetangx.com 可以注册个账号去听数据结构课程,老师讲的特好。 我的代码是按

    相关 LCS 公共序列

    首先要明白什么是子序列,什么是子串; 设:主串长度为n; 子序列:从主串中抽出少于n的元素组成的序列(这些抽出的元素比一定是连续的他们的相对位置不变);