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

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

前言:

一个给定序列的子序列,就是将给定的序列中零个或多个元素去掉后得到的结果。其形式化定义如下:给定一个序列X={x1,x2,x3,x4….Xn},另一个序列Z={z1,z2,z3,z4……Zn}满足如下条件时称为X的子序列,即存在一个严格递增的X下表序列(i1,i2…….ik),对所有j=1,2,3,…..k满足xi=zj例如Z=是X=的子序列对应的下标的序列为<2,3,5,7>

给定两个序列X,Y,如果Z即使X的序列又是Y的子序列我们称X和Y的公共子序列

问题描述:

给定两个序列X{x1,x2,x3,……xm}和Y={y1,y2,y3…..yn}求X和Y长度最长的公共最长子序列 简称LCS问题

问题的解决:

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

前缀的严格定义:

给定一个序列X=对i=0,1,2…..m,定义X的第i前缀为Xi=例如:X则X4=,X0为空串

LCS的最优子结构:

X=1,x2,…,xm> 和 Y=1,y2,…,yn>为两个序列的,Z=为X和Y的任意LCS

如果xm= yn,那么zk=xm= yn而且Zk-1是Xm-1和 Yn-1的一个LCS

如果xm≠ yn,那么zk≠xm蕴含Z是Xm-1和 Y的一个LCS

如果xm≠ yn,那么zk≠yn蕴含Z是X和 Yn-1的一个LCS

动态规划之最长公共子序列(LCS)_第1张图片

v 步骤2:一个递归解

   c[i,j]为序列Xi 和Yj一个LCS的长度

动态规划之最长公共子序列(LCS)_第2张图片

v 步骤3:一个递归解计算LCS长度

动态规划之最长公共子序列(LCS)_第3张图片

动态规划之最长公共子序列(LCS)_第4张图片

步骤4构造LCS

我们可以利用LCS_LENGTH返回的表b快速构造X

和Y=只需简单的从b[m][n]开始并按箭头方向进行追踪下去即可。当在表b[i][j]中遇到一个左上箭头意味着xi=yj是LCS的一个元素

伪代码:

PRINT_LCS(b,X,i,j)

1 if i==0orj==0

2    return

3if b[i,j]==”左上箭头”

4    PRINT_LCS(b,X,i-1,j-1)

5    print xi

6 elseif n[I,j]==”上箭头”

7    PRINT_LCS(b,X,i-1,j-1)

 8else PRINT_LCS(b,X,i,j-1)

--------------------------------C++对以上算法的实------------------------------------

#define MaxNumber 20
char b[MaxNumber][MaxNumber];
static int Mem[20];
int num=0;
void LCS_LENGTH(char X[],char Y[],int Xlength,int Ylength)
{
int m=Xlength;
int n=Ylength;
int c[MaxNumber][MaxNumber];
for(int i=0;i<=m;i++)
c[i][0]=0;
for(int j=0;j<=n;j++)
c[0][j]=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(X[i]==Y[j])
{
c[i][j]=c[i-1][j-1]+1;
       b[i][j]='!';
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]='@';


}
else
{
c[i][j]=c[i][j-1];
b[i][j]='#';
}
}
}
}
int PRINT_LCS(char b[MaxNumber][MaxNumber],char X[],int Xlength,int Ylength)


if(Xlength==0||Ylength==0)
return 1;
if(b[Xlength][Ylength]=='!')
{
PRINT_LCS(b,X,Xlength-1,Ylength-1);
Mem[num++]=Xlength;
cout<<"X-"<    }
else if(b[Xlength][Ylength]=='@')
{
PRINT_LCS(b,X,Xlength-1,Ylength);
}
else PRINT_LCS(b,X,Xlength,Ylength-1);
}
void main()
{
int xlength,ylength;
char X[]={'0','A','F','C','B','D','A','B','D','G','T'};
char Y[]={'0','A','B','C','A','B','A','G','R','T'};
xlength=sizeof(X)/sizeof(char);
ylength=sizeof(Y)/sizeof(char);
LCS_LENGTH(X,Y,xlength-1,ylength-1);
PRINT_LCS(b,X,xlength-1,ylength-1);
cout<for(int i=1;i<=xlength;i++)
cout<cout<for(int i=1;i<=ylength;i++)
cout<cout<cout<<"最长公共子序列:";
for(int i=0;icout<
}

你可能感兴趣的:(数据结构与算法)