0
点赞
收藏
分享

微信扫一扫

最长公共子序列LCS问题

忍禁 2022-02-02 阅读 87

输入两个序列(以定义数组赋初值给定值),输出如教材P68页所示的优化函数表表3.7和标记函数表表3.8(提示:↑↖←三个符号可用数值1,0,-1代替处理,只有输出时才输出这个符号),及最长公共子序列。测试数据为:

1组:X:<A,B,C,B,D,A,B>     Y:<B,D,C,A,B,A>

2组:X:<1,3,4,5,6,7,7,8>     Y:<3,5,7,4,8,6,7,8,2>

#include <iostream>
#include <stdio.h>
using namespace std; 
char x[100]={0,'A','B','C','B','D','A','B'},y[100]={0,'B','D','C','A','B','A'};//两个序列 
//char x[100]={0,'1','3','4','5','6','7','7','8'},y[100]={0,'3','5','7','4','8','6','7','8','2'};//第二组测试数据
int c[100][100]={0},z[100];//c[i][j]表示xi,yi的最长公共子序列,z[100]记录X和Y相同序列在X的位置 
char b[100][100];//b[i][j]是标记函数,1代表"↑",2代表"←",3代表"↖" 
void recall(int i,int j)//应用递归算法输出解的追踪过程 
{
	if(j==0)  cout<<"j=0"<<endl<<endl;//当j为0时,Y序列为空输出标识j=0 
	else if(i==0) cout<<"i=0"<<endl<<endl;//当i为0时,X序列为空输出标识i=0 
	else
	{
		printf("B[%d,%d]→",i,j);//输出追踪过程
		if(b[i][j]=='3') recall(i-1,j-1);//3代表"↖" ,斜向上走 
		if(b[i][j]=='2') recall(i,j-1);//2代表"←",向左走 
		if(b[i][j]=='1') recall(i-1,j);//1代表"↑",向上走 
	} 
}
void refind(int i,int j,int k)//应用递归算法得出解 
{
	if(j==0||i==0)//X或Y序列为空结束 
	{
		cout<<"”↖“"<<endl<<endl;//输出标识”↖“
		return;//结束 
	}
	if(b[i][j]=='3')//3代表"↖" ,斜向上走 
	{
		z[++k]=i;//z[++k]记录X和Y相同序列在X的位置
		printf("B[%d,%d]=",i,j);//输出b[i][j]为↖的情况 
		refind(i-1,j-1,k);
	}
	if(b[i][j]=='2') refind(i,j-1,k);//2代表"←",向左走 
	if(b[i][j]=='1') refind(i-1,j,k);//1代表"↑",向上走 
}
void findArray(int m,int n)//动态规划寻找最长公共子序列 
{
	for(int i=1;i<=m;i++)//前面c[100][100]={0}的操作已使c[0][j]和c[i][0]=0了 
		for(int j=1;j<=n;j++)
			if(x[i]==y[j])
			{
				c[i][j]=c[i-1][j-1]+1;//c[i][j]存储最大子序列长度
				b[i][j]='3';//标记函数b[i][j]='↖'
			}
			else if(c[i-1][j]>=c[i][j-1])//max{c[i-1][j],c[i][j-1]} 
			{
				c[i][j]=c[i-1][j];//c[i][j]存储最大子序列长度
				b[i][j]='1';//b[i][j]='↑'
			} 
			else
			{
				c[i][j]=c[i][j-1];//c[i][j]存储最大子序列长度
				b[i][j]='2';//标记函数b[i][j]='←' 
			} 
	cout<<"优化函数c[i,j]如下:"<<endl;
	for(int i=0;i<=m;i++)//输出优化函数
	{
		for(int j=1;j<=n;j++)
			printf("c[%2d,%2d]=%2d  ",i,j,c[i][j]);
		cout<<endl;
	}
	cout<<"标记函数b[i,j]如下:"<<endl;
	for(int i=1;i<=m;i++)//输出标记函数 
	{
		for(int j=1;j<=n;j++)
		{
			printf("b[%2d,%2d]=",i,j);//输出
			if(b[i][j]=='1') printf("↑  ");//3代表"↖" ,斜向上走 
			if(b[i][j]=='2') printf("←  ");//2代表"←",向左走 
			if(b[i][j]=='3') printf("↖  ");//1代表"↑",向上走 
		}
		cout<<endl;
	}
	cout<<"解的追踪过程为:"<<endl;//输出解释 
	recall(m,n);//应用递归算法输出解的追踪过程 
	cout<<"其中";
	refind(m,n,0);//应用递归算法得出解 
	cout<<"这就得出解z=<";
	for(int k=c[m][n];k>=1;k--)//输出相同的子序列在x的位置 
	{
		if(k==1) cout<<'x'<<z[k]<<">=<";//最后一个数据输出 
		else cout<<'x'<<z[k]<<',';//逗号隔开 
	}
	for(int k=c[m][n];k>=1;k--)//输出相同的子序列 
	{
		if(k==1) cout<<x[k]<<'>'<<endl<<endl;//最后一个输出 
		else cout<<x[k]<<',';//逗号隔开
	}	
}
int main()
{
	int m=7,n=6;//序列x和y的长度
	//int m=8,n=9;//第二组测试数据 
	findArray(m,n);//动态规划寻找最长公共子序列 
}

 运行结果

举报

相关推荐

0 条评论