动态规划之最长公共子序列

来源:互联网 发布:吴江js华腾公寓自提柜 编辑:程序博客网 时间:2024/06/07 02:29

先来看一下基本概念

1、公共子序列:给定两个序列X和Y,如果Z既是X的子序列,又是Y的子序列,那么称Z是X和Y的公共子序列。

2、最长公共子序列:求公共子序列中长度最长的。

最长公共子序列问题,简称LCS问题,下边说一下求解思路:

步骤一:刻画最长公共子序列的特征:

前缀:给定一个序列X={x1,x2,x3...xm},对于i=1...m,定义X的第i前缀Xi={x1,x2,..xi};

结论:两序列的LCS包含两序列的前缀的LCS。因此,LCS问题具有最优子结构性质。

步骤二:

定义c[i,j]表示X和Y的LCS长度,下边给出递归式:


步骤三:

自底向上的动态规划方法:

void LCS_down2up(DataType X[],int m,DataType Y[],int n,int c[M+1][N+1],char b[M+1][N+1]){    for(int i=1;i<=m;i++)    {        for(int j=1;j<=n;j++)        {            if(X[i-1]==Y[j-1])            {                c[i][j]=c[i-1][j-1]+1;                b[i][j]='D'; //D means diagonal(对角线)            }            else            {                c[i][j]=max(c[i-1][j],c[i][j-1]);                if(c[i-1][j]>c[i][j-1])                    b[i][j]='T';  // T means top                else b[i][j]='L';  // L means left            }        }    }}
c数组保存最大子序列长度,b数组记录子问题的调用方向


步骤四、构造LCS

void print_result(char b[M+1][N+1],DataType X[],int i,int j){    if(i==0 || j==0) ;    else {    if(b[i][j]=='D')    {        print_result(b,X,i-1,j-1);        cout<<X[i-1];    }    else if(b[i][j]=='T')        print_result(b,X,i-1,j);    else print_result(b,X,i,j-1);    }}

其实最大公共子序列并非只有一个,我们所做的只是找出了满足条件的一个最优解而已,所以在运行测试代码时,我们构造解的起点不同,最后打印的LCS也不同。

测试代码

#include <iostream>#define M 7#define N 6typedef char DataType;using namespace std;//down to topvoid LCS_down2up(DataType X[],int m,DataType Y[],int n,int c[M+1][N+1],char b[M+1][N+1]){    for(int i=1;i<=m;i++)    {        for(int j=1;j<=n;j++)        {            if(X[i-1]==Y[j-1])            {                c[i][j]=c[i-1][j-1]+1;                b[i][j]='D'; //D means diagonal(对角线)            }            else            {                c[i][j]=max(c[i-1][j],c[i][j-1]);                if(c[i-1][j]>c[i][j-1])                    b[i][j]='T';  // T means top                else b[i][j]='L';  // L means left            }        }    }}void print_result(char b[M+1][N+1],DataType X[],int i,int j){    if(i==0 || j==0) ;    else {    if(b[i][j]=='D')    {        print_result(b,X,i-1,j-1);        cout<<X[i-1];    }    else if(b[i][j]=='T')        print_result(b,X,i-1,j);    else print_result(b,X,i,j-1);    }}int main(){    DataType X[]={'a','b','c','b','d','a','b'},Y[]={'b','d','c','a','b','a'};    int c[M+1][N+1]={0};    char b[M+1][N+1]={0};    LCS_down2up(X,M,Y,N,c,b);    cout<<"the list of result : "<<endl;    for(int i=1;i<M+1;i++)    {        for(int j=1;j<N+1;j++)        {            cout<<c[i][j]<<"\t";        }        cout<<endl;    }    cout<<"b list:"<<endl;    for(int i=1;i<M+1;i++)    {        for(int j=1;j<N+1;j++)        {            cout<<b[i][j]<<"\t";        }        cout<<endl;    }    print_result(b,X,6,6);    cout<<endl;    print_result(b,X,7,6);    return 0;}


原创粉丝点击