首页 > 代码库 > 算法实验--最长子序列

算法实验--最长子序列

一、实验目的:

熟悉掌握动态规划法设计技术

二、实验要求:

1按教材所授内容要求,完成“最长公共子序列问题”算法。得到一个完整正确的程序。

2、问题规模:不少于100

3、输出最终结果。

三、实验设备:

PC机一台

Vc++6.0编译软件一套

四、问题描述:

若给定序列X={x1,x2,,xm},则另一序列Z={z1,z2,,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,,ik}使得对于所有j=1,2,,k有:zj=xij。例如,序列Z={BCDB}是序列X={ABCBDAB}的子序列,相应的递增下标序列为{2357}。给定2个序列XY,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列XY的公共子序列。给定2个序列X={x1,x2,,xm}Y={y1,y2,,yn},找出XY的最长公共子序列。 

例如:“ABCBDAB” 和 “BDCABA”  的最长公共子序列为: BCBA 

  或者“ABHC898987fjgij”和“ABCIEJGF89895f55fg”的公共子序列为:ABC8989fg

五、算法分析:

设定有两个序列,分别是Xm)和Yn),即是M个元素的X序列和有N个元素的Y序列,设序列X={x1,x2,x3,....xm}Y={y1,y2,y3.....yn}的最长公共子序列Z={z1,z2,z3....zk};那么根据动态规划求最优解原理,有:

(1) xm=yn,zk=xm=yn,Z(k-1)X(m-1)Y(n-1)的最长公共子序列。

(2) xm!=yn,zk=xm,则ZX(m-1)Y的最长公共子序列。

(3) xm=yn,且zk=yn,则ZXY(n-1)的最长公共子序列。

其中,X(m-1)={x1x2x3......x(m-1)};Y(n-1)={y1,y2,y3......y(n-1)};

Z(k-1)={z1,z2,z3.......z(k-1)}

证明:(1)反证法。zk=xm,则{z1,z2,z3...zk,zm}XY的长度为k+1的公共子序列。这与ZXY的最长公共子序列矛盾。因此,必有zk=xm=yn.由此可知Z(k-1)X(m-1)Y(n-1)的长度为k-1的公共子序列。若X(m-1)Y(n-1)有长度大于k-1的公共子序列W,则将Xm加在其尾部产生XY的长度大于k的公共子序列。此为矛盾。故Z(k-1)X(m-1)Y(n-1)的最长公共子序列。

(2)由于zk=xmZX(m-1)Y的公共子序列。若X(m-1)Y有长度大于k的公共子序列W,则W也是XY的长度大于k的公共子序列。这与ZXY的最长子序列矛盾。由此可知,ZX(m-1)Y的最长公共子序列。

(3)本实验采用随机生成【0-9】【A-Z】【a-z】之间的数字和字母和手动输入字符串X(M)Y(N)两种方式求得最长子序列的解。

用到的函数有:

void InputLCS(char *x,char *y,int B[][N+1]).通过手动输入求解函数。

void RandLCS(const int m,const int n,char *x,char *y,int B[][N+1]).通过随机生成字符串求解。

void LCSLength(int m,int n,char x[M+1],char y[N+1],int b[M+1][N+1]),

void LCS(int i,int j,char x[M+1],int b[M+1][N+1])。此两个函数式求解关键函数,前者求出最优解并将子序列长度存放在局部变量c[m][n]中并显示出来,后者将最长子序列以字符串的形式显示在屏幕上。

void printRand(char x[],const m)。是随机生成字符串并输出的函数,是随机生成字符串方式的重要函数。

 

六、代码:

#include <stdio.h>

#include<stdlib.h>

#include<time.h>

#include<string.h>

#define M 150

#define N 150

void LCSLength(int m,int n,char x[M+1],char y[N+1],int b[M+1][N+1]);

void LCS(int i,int j,char x[M+1],int b[M+1][N+1]);

void printRand(char x[],const m);

void InputLCS(char *x,char *y,int B[][N+1]);

void RandLCS(const int m,const int n,char *x,char *y,int B[][N+1]);

void main(){

int choose; 

char X[M+1],Y[N+1]; 

int B[M+1][N+1];

printf("---------请选择求最长子序列方式----------\n");

printf("---------------1.手动输入----------------\n");

printf("---------------2.随机生成----------------\n");

printf("---------------0.退出--------------------\n");

scanf("%d",&choose);

switch(choose)

{

case 1:

InputLCS(X,Y,B);

break;

case 2:

RandLCS(M,N,X,Y,B);

break;

case 0:

exit(0);

}

printf("\n");

}

 

//生成随机数并显示出来,随机生成部分

void printRand(char x[],const int m)

{

for(int i=0;i<m;i++)

{

x[i]=(rand()%75+48);//0-9(48-57),A-Z(65-90),a-z(97-122)

//若在数字与大写字母之间则+7得到大写字母

if(x[i]>57&&x[i]<65)x[i]=x[i]+7;

//若在大小写字母之间则+6得到小写字母

else if(x[i]>90&&x[i]<97)x[i]=x[i]+6;

printf("%c",x[i]);

}

}

//处理随机生成方式求最长子序列

void RandLCS(const int m,const int n,char *x,char *y,int B[][N+1])

{

srand(time(NULL));

printf("生成字符串a(长度%d)\n",m);

printRand(x,m);

printf("\n生成字符串b(长度%d)\n",n);

printRand(y,n);

LCSLength(M,N,x,y,B); 

printf("\n公共子序列结果:");

LCS(M,N,x,B);

}

 

//处理手动输入方式求最长子序列

void InputLCS(char *x,char *y,int B[][N+1])

{

int lx,ly;

printf("输入字符串a\n");

scanf("%s",x+1); 

printf("输入字符串b\n");

scanf("%s",y+1); 

lx=strlen(x+1); 

ly=strlen(y+1); 

printf("\n字符串a长度la=%d; 字符串b长度lyb=%d",lx,ly);

LCSLength(lx,ly,x,y,B); 

printf("\n公共子序列结果:");

LCS(lx,ly,x,B);

}

 

//求出子序列的最优解存放在c[m][n]

void LCSLength(int m,int n,char x[],char y[],int b[M+1][N+1])

int i,j; 

int c[M+1][N+1]; 

for (i=1;i<=m;i++) 

c[i][0]=0; 

for (i=1;i<=n;i++) 

c[0][i]=0; 

for (i=1;i<=m;i++) 

for (j=1;j<=n;j++) 

if (x[i]==y[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]=2; 

else 

c[i][j]=c[i][j-1]; 

b[i][j]=3; 

}

printf("\n公共子序列长度length:%d",c[m][n]);

}

//输出最长子序列的结果

void LCS(int i,int j,char x[],int b[M+1][N+1])

if (i==0 || j==0) 

return; 

if (b[i][j]==1) 

LCS(i-1,j-1,x,b); 

printf("%c",x[i]); 

else if(b[i][j]==2) 

LCS(i-1,j,x,b); 

else LCS(i,j-1,x,b);

}

七、调试及运行:

1.手动输入字符串运行结果:

 

 

 

2.自动生成字符串方式,其中生成50个元素效果如下:

 

 

 

 

 

 

 

 

 

 

3.和结果2相似,生成元素为100个:

 

 

 

4.生成元素个数为150时,效果如下:

 

算法实验--最长子序列