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

本文介绍了动态规划的基本概念,通过最长公共子序列(LCS)问题详细阐述了动态规划的四个步骤:判断最优子结构、构建递归解、计算LCS长度及构造LCS。并通过一个实例展示了如何实现LCS算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划并不是一种算法,而是一种解决问题的思路。典型的动态规划问题,如最长公共子序列(LCS),最长单调子序列(LIS)等。

动态规划分为四个步骤:

1.判断问题是否具有最优子结构

这里以LCS为例,X={x1,x2,...,xi};Y={y1,y2,...,yj}。最长公共子序列Z={z1,z2,...,zk};

①如果xi=yj,那么zk=xi=yj,且Zk-1是序列Xi-1和Yj-1的LCS;

②如果xi≠yj,那么zk≠xi;且Zk是序列Xi-1和Yj的LCS;

③如果xi≠yj,那么zk≠yj;且Zk是序列Xi和Yj-1的LCS;

可以用反证法证明上述子结构的成立。

2.一个递归解

设c[i,j]是Xi和Yj的LCS的长度,i=0或j=0时,c[i,j]=0;

c[i,j]=0   (i=0或j=0)

c[i,j]=c[i-1,j-1]   (i,j>0;xi=yj)

c[i,j]=max{c[i-1,j],c[i,j-1]}   (i,j>0;xi≠yj)

3.计算LCS的长度

c[i,j]为递归解,那么有多少个不同的递归解呢?O(m*n)。即要有重叠子问题,而不是每次都要解决新的问题。至于重叠子问题,需从底向上求。每次只需索引之前较小规模的子问题即可。

从底向上,求解c[i,j]。还需维护b[i][j]以简化最优解的结构。

例如,设所给的两个序列为X=<A,B,C,B,D,A,B>和Y=<B,D,C,A,B,A>。由算法LCS_LENGTH和LCS计算出的结果如图2所示。

 

 j 0 1 2 3 4 5 6 
i  yj B D C A B A 
  
0xi  0 0 0 0 0 0
          
1A0 0 0 0 11 1
            
2B0 111 1 22
          
3C0 1 1 22 2 2
          
4B0 1 1 2 2 33
         
5D0 1 2 2 2 3 3
         
6A0 1 2 2 3 3 4
         
7B0 1 2 2 3 4 5
  

void LCS_LENGTH(char x[],char y[],const int len_x,const int len_y,int c[][ROW],int b[][ROW])
{
	int i,j;

	for(i=1;i<len_x;i++)
	{
		for(j=1;j<len_y;j++)
		{
			if(x[i]==y[j])
			{
				c[i][j]=c[i-1][j-1]+1;
				b[i][j]=3;	//3=="↖"
			}
			else
				if(c[i-1][j]>=c[i][j-1])
				{
					c[i][j]=c[i-1][j];
					b[i][j]=1;	//1=="↑"
				}
				else
				{
					c[i][j]=c[i][j-1];
					b[i][j]=2;	//2=="←"
				}
		}//for j
	}//for i

}

4.构造一个LCS

根据表b[i][j]构造LCS,

3=="↖",表示x[i]在Zk中;

1=="↑",表示x[i]不在Zk中,且向c[i][j]=c[i-1][j];

2=="←",表示x[i]不在Zk中,且向c[i][j]=c[i][j-1];
void PRINT_LCS(int b[][ROW],char x[],int m,int n)
{
	if(m==0||n==0)
		return;

	if(b[m][n]==3)
	{
		PRINT_LCS(b,x,m-1,n-1);
		printf("%c\t",x[m]);
	}
	else if(b[m][n]==1)
	{
		PRINT_LCS(b,x,m-1,n);
	}
	else
	{
		PRINT_LCS(b,x,m,n-1);
	}
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值