最长公共子序列(DP)

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

算法思想:用一个二维数组c来表示两个串的字串的公共子序列个数,比如c[i][j]表示的是,x[0…i]和y[0…j]的最长公共子串,因为当任意子串长度为0时,没有公共子序列,可以得:c[0][0…n]=0,c[0…m][0]=0(m,n为字符串x,y的长度),

当x[i]==y[j]时,也就是说,两个子串的最后一个字符相同,他们的最长公共子序列一定包含了x[i],显然,c[i][j]=c[i-1][j-1]+1,即当前的子串的最长公共子序列,等于两个子串长度-1的最长公共子序列,再+1(因为我们减去的x[i]和y[j]相等,是他们的公共子序列),

当[i]!=y[j]时,c[i][j]=max{c[i-1][j],c[i][j-1]},两个子串的最后一个元素不同,所以,两个子串的最大公共子序列的最后一个元素一定不是他们的最后一个元素,因为他们根本就不等,怎么可能成为一个公共元素,只有可能是c[i-1][j]或c[i][j-1],也就是其中一个子串最后一个元素不构成子串的最大公共子序列,再取两者的最大值即可。
b[i][j]用来记录c[i][j]的值是由哪个子问题得到的,由LCS()来得出最长公共子序列。

#include"stdio.h"
#include"stdlib.h"
#include"string.h"
void LCSLength(int m,int n,char* x,char* y,int** c,int** b){
	int i,j;//i,j为两个字符串的下标,c[i][j]为当str1和str2长度为i,j时的最长公共子序列 
	//当其中一个字符串为空时,没有公共子序列
	for(i=0;i<=m;i++)
		c[i][0] = 0;
	for(j=0;j<=n;j++)
		c[0][j] = 0;
	/*DP求解,分两种情况:
	1、x[i]==y[j],c[i][j] = c[i-1][j-1]+1
	2、x[i]!=y[j],c[i][j] = max(c[i][j-1],c[i-1][j]) 
	*/
	for(i=1;i<=m;i++){
		for(j=1;j<=n;j++){
			if(x[i-1]==y[j-1]){
				c[i][j]=c[i-1][j-1] + 1;
				b[i][j]=1;
			}
			else{
				if(c[i][j-1]>c[i-1][j]){
					c[i][j]=c[i][j-1];
					b[i][j]=2;
				}
				else{
					c[i][j]=c[i-1][j];
					b[i][j]=3;
				}
			}
		}
	}
	printf("len=%d\n",c[m][n]);
}
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);
		printf("%c",x[i-1]);
	}
	else if(b[i][j]==2)
		LCS(i,j-1,x,b);
	else 
		LCS(i-1,j,x,b);
}
int main(){
	char x[100]={'\0'},y[100]={'\0'};
	gets(x);
	gets(y);
	int m = strlen(x);
	int n = strlen(y);
	//二维数组c多申请一行一列,表示其中有字符串的长度为 0 ,b[i][j]数组记录c[i][j]是由哪个子问题的解得到的 
	int **c=(int **)malloc(sizeof(int *)*(m+1));
	int **b=(int **)malloc(sizeof(int *)*(m+1));
	for(int i = 0;i<m+1;i++){
		c[i]=(int*)malloc(sizeof(int)*(n+1));
		b[i]=(int*)malloc(sizeof(int)*(n+1));
	}
	LCSLength(m,n,x,y,c,b);
	printf("string=");
	LCS(m,n,x,b);
	return 0;
}






评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值