最长公共子序列

Posted batcaesar-mmm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长公共子序列相关的知识,希望对你有一定的参考价值。

问题描述:

  设集合x,集合y,集合元素若干,求x和y的最长公共子序列。(子序列:给定一个序列,该序列中删去若干元素后得到的序列)

 

备注:

 

  •   编程语言:c++
  •   编译器:Code::Blocks 16.01
  •   操作系统:windows 10

 

源代码:

 

//最长公共子序列

 

/*测试数据
7 6
A B C B D A B
B D C A B A
*/

 

#include<iostream>

 

using namespace std;

 

//计算最长公共子序列长度的动态规划算法LSCLength
void LCSLength(int m,int n,char *x,char *y,int **c,int **b)
{
    int i,j;
    for(i=1; i <= m; i++)
        c[i][0] = 0;
    for(i=1; i <= n;i++)
        c[0][i] = 0;
    for(i=1; i <= m; i++)
        for(j=1; j <= m; j++)
        {
            if(x[i] == y[j])
            {
                c[i][j] = c[i-1][j-1]+1;  //子问题1:c[i][j]值等于斜上方的长度加1
                b[i][j] = 1;
            }
            else if(c[i-1][j] >= c[i][j-1])
            {
                c[i][j] = c[i-1][j];  //子问题2:c[i][j]值等于上面的长度
                b[i][j] = 2;
            }
            else
            {
                c[i][j] = c[i][j-1];  //子问题3:c[i][j]值等于左面的长度
                b[i][j] = 3;
            }
        }
}

 

//LCS实现根据b的内容打印出x和y最长公共子序列
void LCS(int i,int j,char *x,int **b)
{
    if(i==0 || j==0)
        return;
    if(b[i][j] == 1)
    {
        LCS(i-1,j-1,x,b);
        cout<<x[i];
    }
    else if(b[i][j] == 2)
        LCS(i-1,j,x,b);
    else
        LCS(i,j-1,x,b);
}

 

int main()
{
    int mm,nn;  //mm:xx集合元素个数  yy集合元素个数
    char *xx,*yy;
    int **cc,**bb;

 

    cout<<"分别输入x和y集合元素个数:"<<endl;
    cin>>mm>>nn;

 

    xx = new char[mm+1];  //xx集合
    yy = new char[nn+1];  //yy集合
    //输入数据
    cout<<"x集合元素:"<<endl;
 for(int r=1;r<=mm;r++)
        cin>>xx[r];
    cout<<"y集合元素:"<<endl;
 for(int r=1;r<=nn;r++)
        cin>>yy[r];

 

    //创建动态二维数组
    cc = new int*[mm+1];  //cc[i][j]存储xx和yy的最长公共子序列的长度
 bb = new int*[mm+1];  //bb[i][j]记录cc[i][j]的值是由哪个子问题得到的
 /*子问题:
 1--cc[i][j] = cc[i-1][j-1]+1  (斜上方的长度加1)
 2--cc[i][j] = cc[i-1][j]  (等于上面的长度)
 3--cc[i][j] = cc[i][j-1]  (等于左边的长度)
 */
 for(int i=0;i<=mm; i++)
 {
  cc[i] = new int[nn];
  bb[i] = new int[nn];
 }

 

 //赋初值
 for(int j=0;j<=mm;j++)
    {
        for(int k=0;k<=nn;k++)
        {
            cc[j][k]=-1;
            bb[j][k]=-1;
        }
    }

 

    cout<<endl;
    LCSLength(mm,nn,xx,yy,cc,bb);

 

    //输出二维数组
    cout<<"c[i][j]存储x和y的最长公共子序列的长度:"<<endl;
    for(int j=0;j<=mm;j++)  //输出cc[i][j],cc[i][j]存储xx和yy的最长公共子序列的长度
    {
        for(int k=0;k<=nn;k++)
            cout<<cc[j][k]<<" ";
        cout<<endl;
    }
    cout<<endl;

 

    cout<<"b[i][j]记录c[i][j]的值是由哪个子问题得到的:"<<endl;
    cout<<"1--cc[i][j] = cc[i-1][j-1]+1  (斜上方的长度加1)"<<endl;
    cout<<"2--cc[i][j] = cc[i-1][j]  (等于上面的长度)"<<endl;
    cout<<"3--cc[i][j] = cc[i][j-1]  (等于左边的长度)"<<endl;
    for(int j=0;j<=mm;j++)  //输出bb[i][j],bb[i][j]记录cc[i][j]的值是由哪个子问题得到的
    {
        for(int k=0;k<=nn;k++)
            cout<<bb[j][k]<<" ";
        cout<<endl;
    }

 

    cout<<endl;
    cout<<"最长公共子序列:";
    LCS(mm,nn,xx,bb);
    cout<<endl;

 

    //释放空间
    delete[] xx;
    delete[] yy;

 

    for(int i=0;i<=nn;i++)
 {
  delete[] cc[i];
  delete[] bb[i];
 }
    delete[] cc;
    delete[] bb;

 

    return 0;
}
 
运行界面:
技术图片

 

 

以上是关于最长公共子序列的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子序列的应用

C语言实现最长公共子串与最长公共子序列

最长递增子序列 && 最大子序列最长递增子序列最长公共子串最长公共子序列字符串编辑距离

codevs 1862 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)

最长公共子串和最长公共子序列

最长公共子串与最长公共子序列