首页 > 其他 > 详细

最长公共子序列

时间:2014-04-27 10:38:14      阅读:515      评论:0      收藏:0      [点我收藏+]

给定两个序列X=<x1,x2,x3,x4…xm>和Y=<y1,y2,y3,y4…yn>,求X和Y长度最长的公共子序列。

可以用动态规划的方法解决这个问题,建立数组c[i][j],i和j分别表示Xi 和Yj的的LCS长度,如果i=0,j=0,c[i][j]=0,根据最优子结构的性质,得到问题的递推公式为:

bubuko.com,布布扣             

建立数组b[i][j],如果b[i][j]=0,代表c[i][j]=c[i-1][j-1]+1的情况,如果b[i][j]=-1,代表c[i][j]=c[i][j-1]的情况,如果b[i][j]=1,代表c[i][j]=c[i-1][j]的情况。数组b[i][j]在递归地构造LCS时会用到。

程序为:

# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define N 100
int main()
{
	int f1(char *a,char *b,int c[][N],int d[][N]);
	void print(int b[][N],char *a,int i,int j);
	char a[20]="abcrty";
	char b[20]="aerbtyc";
	int c[N][N];
	int d[N][N];
	int i,j;
	char *s=0; 
	f1(a,b,c,d);
	print(d,a,strlen(a),strlen(b));
system("pause");
return 0;
}
int f1(char *a,char *b,int c[][N],int d[][N])
{
int lena=strlen(a);
int lenb=strlen(b);
int i=0;
int j=0;
for(i=0;i<=lena;i++)              //c[i][j]的初始化
	c[i][0]=0;
for(j=0;j<=lenb;j++)
	c[0][j]=0;
for(i=1;i<=lena;i++)              //递推公式
	for(j=1;j<=lenb;j++)
	{
	if(a[i-1]==b[j-1]){
		c[i][j]=c[i-1][j-1]+1;
		d[i][j]=0;
	}
	else if(c[i-1][j]>c[i][j-1]){
		c[i][j]=c[i-1][j];
		d[i][j]=1;
	}
	else
	{
		c[i][j]=c[i][j-1];
		d[i][j]=-1;
	}
	}
	return 0;
}

void print(int b[][N],char *a,int i,int j)   //递归的方法构造LCS
{
	if(i==0||j==0)
		return ;

	if(b[i][j]==0){
		print(b,a,i-1,j-1);
		printf("%c\t",a[i-1]);
	}
	else if (b[i][j]==1)
		print(b,a,i-1,j);
	else
		print(b,a,i,j-1);
}

上面的代码使用了附加空间b数组,在构造LCS时采用了递归,因为程序的效率较低,对上面的代码稍作优化,不使用数组b,构造用循环的方式构造LCS。代码如下:

# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define N 100
int main()       
{
	int f(char *a,char *b,int c[][N]);
	char * lcs(char s[],char *a,char *b,int c[][N]);
	char a[20]="abcrty";
	char b[20]="aerbtyc";
	int c[N][N];
	int d[N][N];
	int i,j;
	char *s=0; 
	f(a,b,c);
	s=lcs(s,a,b,c);
	printf("%s\n",s);
system("pause");
return 0;
}

int f(char *a,char *b,int c[][N])
{
int lena=strlen(a);
int lenb=strlen(b);
int i=0,j=0;
for(i=0;i<=lena;i++)    //初始化
	c[i][0]=0;
for(j=0;j<=lenb;j++)
	c[0][j]=0;
for(i=1;i<=lena;i++)       //递推公式
	for(j=1;j<=lenb;j++)
	{
	if(a[i-1]==b[j-1])
		c[i][j]=c[i-1][j-1]+1;
	else if(c[i-1][j]>c[i][j-1])
		c[i][j]=c[i-1][j];
	else
		c[i][j]=c[i][j-1];
	}
	return c[lena][lenb];
}

char * lcs(char s[],char *a,char *b,int c[][N])
{
int i=strlen(a);
int j=strlen(b);
int k=f(a,b,c);
s=(char *)malloc(k*sizeof(char));
s[k]=‘\0‘;
while(k>0)
{
	if(c[i][j]==c[i-1][j])
		i--;
	else if(c[i][j]==c[i][j-1])
		j--;
	else 
	{
	
	s[--k]=a[i-1];
	i--;j--;
	}
}
return s;       //最长公共子序列
}



最长公共子序列,布布扣,bubuko.com

最长公共子序列

原文:http://blog.csdn.net/u011608357/article/details/24527057

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!