Longest Common Sequence Algorithm(最长公序列算法)

本文探讨了最长公共子序列(LCS)问题,这是一个在算法中常见的动态规划题目。文章详细介绍了LCS的最优子结构,并提出了两种解法,包括一个直观的递归算法和一个使用二维矩阵实现的O(mn)时间复杂度的高效算法。
摘要由CSDN通过智能技术生成

      问题描述: 在最长公共子序列问题中,给定了两个序列 X=<X1, X2, ..., Xm>和Y=<Y1, Y2, ..., Yn>,希望找出X和Y的最大长度公共序列。

      LCS是动态规划算法中比较经典的问题。

          1、构造LCS的最优子结构:

                设X=<X1, X2, ..., Xm>和Y=<Y1, Y2, ..., Yn>为两个序列,并设Z=<Z1, Z2, ..., Zk>为X何Y的任意一个LCS。

                 1)如果Xm = Yn,那么Zk=Xm=Yn而且Zk-1是Xm-1和Yn-1的一个LCS。

                 2)如果Xm != Yn,那么Zk != Xm蕴含Z是Xm-1和Y的一个LCS。

                 3)如果Xm != Yn,那么Zk != Ym蕴含Z是X和Yn-1的一个LCS。

         2、一个递归解:

             

       3、根据前两步,有了下面两种算法,第一种是比较简单且好理解的递归算法;第二种通过两个矩阵保存了动态规划的表格和最长公共子序列。

 

文件:"h1.1"    

#ifndef H1_H
#define H1_H

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<process.h>
#include<math.h>

#define MAXSIZE 100

int LCS_LengthRecursive(char *s, int m, char *t, int n);
void LCS_Length(char *s, int m, char *t, int n, int c[][MAXSIZE], int b[][MAXSIZE]);


#endif


文件“LCS_Length.cpp"

#include "h1.h"

int LCS_LengthRecursive(char *s, int m, char *t, int n){
	
	if(m==0 || n==0){
		return 0;
	}
	else if(s[m] == t[n]){
		return LCS_LengthRecursive(s, m-1, t, n-1)+1;
	}
	else{
		return (LCS_LengthRecursive(s, m-1, t, n)>LCS_LengthRecursive(s, m, t, n-1))?
					LCS_LengthRecursive(s, m-1, t, n):LCS_LengthRecursive(s, m-1, t, n-1);
	}
}

void LCS_Length(char *s, int m, char *t, int n, int c[][MAXSIZE], int b[][MAXSIZE]){

	int i, j;

	for(i=0; i<=m; i++){
		c[i][0] = 0;
	}
	for(j=1; j<=n; j++){
		c[0][j] = 0;
	}

	for(i=1; i<=m; i++){         //As to b[i][j], when b[i][j]=0, means left; 
		for(j=1; j<=n; j++){ //when b[i][j]=1, means diagnoal; when b[i][j]=2, means up.
			if(s[i] == t[j]){
				c[i][j] = c[i-1][j-1] + 1;
				b[i][j] = 1;
			}
			else if(c[i-1][j] >= c[i][j-1]){
				c[i][j] = c[i-1][j];
				b[i][j] = 0;
			}
			else{
				c[i][j] = c[i][j-1];
				b[i][j] = 2;
			}
		}
	}
}

void  PrintLCS(int b[][MAXSIZE], char *s, int m, int n){

	if((m==0) || (n==0)){
		return;
	}
	if(b[m][n] == 1){
		PrintLCS(b, s, m-1, n-1);
		printf("%c ", s[m]);
	}
	else if(b[m][n] == 0){
		PrintLCS(b, s, m-1, n);
	}
	else{
		PrintLCS(b, s, m, n-1);
	}
}

int main(){

	int c[MAXSIZE][MAXSIZE];
	int b[MAXSIZE][MAXSIZE];

	char *s = " cdfabcdefg";
	char *t = " abcdefg";
	
	LCS_Length(s, 10, t, 7, c, b);

	printf("%d\n", c[10][7]);
	PrintLCS(b, s, 10, 7);

	return 0;
}

上述两个算法中,第一个算法即:LCS_LengthRecursive算法的时间复杂度为O( m+n )。

                                第二个算法即:LCS_Length的时间复杂度为O( mn )。

          



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值