最长公共子序列(LCS)问题

一、什么是最长公共子序列
   
    什么是最长公共子序列呢?举个简单的例子吧,一个数列S,若分别是两个或多个已知序列的子序列,且是所有符合条件序列中最长的,则S称为已知序列的最长公共子序列。
 
  举例如下,如:有两个随机数列,1 2 3 4 5 6 和 3 4 5 8 9,则它们的最长公共子序列便是:3 4 5。
 
  一直不明白:最长公共子串和最长公共子序列的区别。
  
   上网查了下,最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。
 
二、蛮力法
 
   蛮力法是解决最长公共子序列问题最容易想到的方法,即对S的每一个子序列,检查是否为T的子序列,从而确定它是否为S和T的公共子序列,并且选出最长的公共子序列。
 
   S和T的所有子序列都检查过后即可求出S和T的最长公共子序列。S的一个子序列相应于下标序列1,2,...,n的一个子序列。因此,S共有2^n个子序列。当然,T也有2^m个子序列。
 
   因此,蛮力法的时间复杂度为O(2^n * 2^m),这可是指数级别的啊。
 
三、动态规划方法
 
   1、序列str1和序列str2
 
  ·长度分别为m和n;
  ·创建1个二维数组L[m.n];
    ·初始化L数组内容为0
    ·m和n分别从0开始,m++,n++循环:
       - 如果str1[m] == str2[n],则L[m,n] = L[m - 1, n -1] + 1;
       - 如果str1[m] != str2[n],则L[m,n] = max{L[m,n - 1],L[m - 1, n]}
    ·最后从L[m,n]中的数字一定是最大的,且这个数字就是最长公共子序列的长度
    ·从数组L中找出一个最长的公共子序列
 
   2、从数组L中查找一个最长的公共子序列
 
   i和j分别从m,n开始,递减循环直到i = 0,j = 0。其中,m和n分别为两个串的长度。
  ·如果str1[i] == str2[j],则将str[i]字符插入到子序列内,i--,j--;
  ·如果str1[i] != str[j],则比较L[i,j-1]与L[i-1,j],L[i,j-1]大,则j--,否则i--;(如果相等,则任选一个)
 
图1 效果演示图
   
   根据上图,我们可以得到其中公共子串:B C B A 和 B D A B。
 
   总感觉,上面这个过程说的不是很清楚,但是不知道怎么才能更加清楚的表述??纠结啊。
四、代码实现

  1.   //代码实现比较简单,有可能不符合规矩,如有哪位前辈看到后,可以指出,我会虚心学习。
  2.   1 #include
    1. <iostream>
    2.   2 #include
      1. <string>
      2.   3 using namespace std
        1. ;
        2.   4
          1. int main(int argc, char **argv)
          2.   5
            1. {
            2.   6
              1. string str1 = "ABCBDAB";
              2.   7
                1. string str2 = "BDCABA";
                2.   8
                3.   9
                  1. int x_len = str1.length();
                  2.  10
                    1. int y_len = str2.length();
                    2.  11
                    3.  12
                      1. int arr[50][50] = {{0,0}};
                      2.  13
                      3.  14
                        1. int i = 0;
                        2.  15
                          1. int j = 0;
                          2.  16
                          3.  17
                            1. for(i = 1; i <= x_len; i++)
                            2.  18
                              1. {
                              2.  19
                                1. for(j = 1; j <= y_len; j++)
                                2.  20
                                  1. {
                                  2.  21
                                    1. if(str1[i - 1] == str2[j - 1])
                                    2.  22
                                      1. {
                                      2.  23
                                        1. arr[i][j] = arr[i - 1][j - 1] + 1;
                                        2.  24
                                          1. }
                                          2.  25
                                            1. else
                                            2.  26
                                              1. {
                                              2.  27
                                                1.  
                                                2.  28
                                                  1. if(arr[i][j - 1] >= arr[i - 1][j])
                                                  2.  29
                                                    1. {
                                                    2.  30
                                                      1. arr[i][j] = arr[i][j - 1];
                                                      2.  31
                                                        1. }
                                                        2.  32
                                                          1. else
                                                          2.  33
                                                            1. {
                                                            2.  34
                                                              1. arr[i][j] = arr[i -1][j];
                                                              2.  35
                                                                1. }
                                                                2.  36
                                                                  1. }
                                                                  2.  37
                                                                  3.  38
                                                                    1. }
                                                                    2.  39
                                                                      1. }
                                                                      2. 41     for(i = 0 ; i <= x_len; i++)
                                                                      3. 42     {
                                                                      4. 43         for( j = 0; j <= y_len; j++)
                                                                      5. 44         {
                                                                      6. 45             cout << arr[i][j] << "  ";
                                                                      7. 46         }
                                                                      8. 47         cout << endl;
                                                                      9. 48     }
                                                                      10. 49     for(i = x_len, j = y_len; i >= 1 && j >= 1;)
                                                                      11. 50     {
                                                                      12. 51             if(str1[i - 1] == str2[j - 1])
                                                                      13. 52             {
                                                                      14. 53                 cout << str1[i - 1] << " ";//倒序打印的
                                                                      15. 54                 i--;
                                                                      16. 55                 j--;
                                                                      17. 56             }
                                                                      18. 57             else
                                                                      19. 58             {
                                                                      20. 59             //  if(arr[i][j -1] >= arr[i - 1][j])//打印:B A D B
                                                                      21. 60                 if(arr[i][j -1] > arr[i - 1][j]) //打印:A B C B
                                                                      22. 61                 {
                                                                      23. 62                     j--;
                                                                      24. 63                 }
                                                                      25. 64                 else
                                                                      26. 65                 {
                                                                      27. 66                     i--;
                                                                      28. 67                 }
                                                                      29. 68             }
                                                                      30. 69     }
                                                                      31. 70     cout << endl;
                                                                      32. 71     return 0;
                                                                      33. 72 }
                                                                      34.  
                                                                          运行结果如下所示。
                                                                      图2 运行效果
                                                                         
                                                                         最后输出为A B C B,则最大子串为B C B A。
                                                                         其实,应该将结果保存起来,然后,正序打印呢。
                                                                       
                                                                       
                                                                       
                                                                          备注:
                                                                         我想还应该有更加优化的方法:求取最大公共子序列。关门了,明天看看。
                                                                         如果哪位前辈知道哪里有更加详细的介绍动态规划求最大公共子序列的资料,可以告诉我下,不胜感激。
                                                                         如果看到这些文字,对于文字中,有哪些不合适合理的地方,请定要指出,也不胜感激,这样我才可以更好的进步。

转载于:https://www.cnblogs.com/For-her/p/3901262.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值