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


    最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。

    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--;(如果相等,则任选一个)
     

    我们可以得到其中公共子串:B C B A 和 B D A B。

    #include <iostream>
    #define N 1000
    using namespace std;
    
    //c[i][j]存储str1[1...i]与str2[1...j]的最长公共子序列的长度
    int c[N][N];
    //flag[i][j]标记是那种子问题
    //flag[i][j]==0为str1[i]==str2[j]
    //flag[i][j]==1为c[i-1][j]>=s[i][j-1]
    //flag[i][j]==-1为c[i-1][j]<s[i][j-1]
    int flag[N][N];
    
    int getLCSlength(string str1, string str2)
    {
        int len1 = str1.size();
        int len2 = str2.size();
        for (int i = 0; i <= len1; i++)
        {
            for (int j = 0; j <= len2; j++)
            {
                if (i == 0 || j == 0)
                    c[i][j] = 0;
                else if (str1[i - 1] == str2[j - 1])
                {
                    c[i][j] = c[i - 1][j - 1] + 1;
                    flag[i][j] = 0;
                }
                else if (c[i - 1][j] >= c[i][j - 1]){
                    c[i][j] = c[i - 1][j];
                    flag[i][j] = 1;
                }
                else{
                    c[i][j] = c[i][j - 1];
                    flag[i][j] = -1;
                }
            }
        }
        return c[len1][len2];
    }
    
    void getLCS(string s1, string s2,int len,char *lcs)
    {
        int i = s1.size();
        int j = s2.size();
        while(i&&j)
        {
            if(flag[i][j]==0)
            {
                lcs[--len] = s1[i-1];
                i--;
                j--;
            }
            else if(flag[i][j]==1) //往上
                i--;
            else if(flag[i][j]==-1)//往左
                j--;
        }
    
    }
    
    int main()
    {
        string str1,str2,lcs;
       char lcs[N];
        cout<<"请输入字符串1:"<<endl;
        cin>>str1;
        cout<<"请输入字符串2:"<<endl;
        cin>>str2;
    
        int lcsLen = getLCSlength(str1,str2);
        cout<<"最长公共子序列长度:"<<lcsLen<<endl;
    
    
        getLCS(str1,str2,lcsLen,lcs);
        cout<<"最长公共子序列为:";
        for(int i=0;i<lcsLen;i++)
            cout<<lcs[i];
        return 0;
    }
  • 相关阅读:
    Xshell4连接,Linux系统中文显示乱码解决办法
    Linux系统英文切换中文
    解决VM安装VMTools后错误提示,实现文件共享
    v
    如何安装VM Tool软件包
    Jbpm工作流表补数记录
    【转】Informix数据表结构分析资料整理之约束查询代码
    storm源码之storm代码结构【译】
    Python学习笔记第一天
    python 连接 redis cluster 集群二种方法
  • 原文地址:https://www.cnblogs.com/home123/p/7450549.html
Copyright © 2020-2023  润新知