最长公共子序列(C语言)

数据结构 专栏收录该内容
42 篇文章 5 订阅

问题: 设X有m个元素,Y有n个元素,求得X和Y的最长公共子序列。

注意:这问题如果用蛮力算法,时间复杂度是指数级别的,不太好。

考虑一下子问题之间的依赖关系(设Z是X和Y的最长公共子序列,有k个元素):

  • 若X最后一个元素==Y最后一个元素,则Z(k-1)是X(m-1)和Y(n-1)的最长公共子序列。
  • 若X最后一个元素!=Y最后一个元素,则Z可以是X(m-1)和Y的最长公共子序列。
  • 若X最后一个元素!=Y最后一个元素,则Z可以是X和Y(n-1)的最长公共子序列。

所以:这个问题满足优化原则和子问题重叠性,可以用动态规划解决它。

最长公共子序列的长度的递推方程(令m = i;n = j;):

在这里插入图片描述

在这里插入图片描述
可惜的是这个方法有一些缺陷,当最长公共子序列的解不唯一的时候,这个代码只能求出一个解。

#include<iostream>
#include<string.h> 
using namespace std;
#define MAXSIZE 100
int B[MAXSIZE][MAXSIZE];		  //B数组用来追踪最长子序列 

void Trace(char*X,int i,int j){
	if(i == 0||j == 0){
		return;
	}	
	if(B[i][j] == 0){//0代表左斜向上
		Trace(X,i-1,j-1);
		cout<<X[i-1]<<" ";
	}
	else if(B[i][j] == 1){//1代表向上
		Trace(X,i-1,j);
	}
	else{//2代表向左
		Trace(X,i,j-1);
	} 
} 


void LCS(char *X,char *Y,int m,int n){
	int C[m+1][n+1]; 
	for(int i = 0;i <= m;i++){
		for(int j = 0;j <= n;j++){
			if(i ==0||j == 0){
				C[i][j] = 0;
			}
			else if(X[i-1] == Y[j-1]){
				C[i][j] = C[i-1][j-1] + 1;
				B[i][j] = 0; //0代表左斜向上	
			}
			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代表向左 
				}
			}
		}
	}	
}

int main(){
	char X[] = "ABCBDAB";
	char Y[] = "BDCABA";
	/*当把一二行的代码换成注释中的代码(即X,Y互换),结果可能会有变化
	char Y[] = "ABCBDAB";
	char X[] = "BDCABA";
	*/
	int m = strlen(X),n = strlen(Y);
	LCS(X,Y,m,n);
	Trace(X,m,n);
	return 0;
	//实际上是有三个解:
	//BCBA
	//BDAB
	//BCAB
}

参考资料:
中国大学MOOK 算法设计与分析 5.8

  • 1
    点赞
  • 0
    评论
  • 17
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值