/*
用动态规划法获得两个序列的最长公共子序列(非连续),如
"ABCBDAB"与"BDCABA"的最长公共子序列为BCAB
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 100
void lcs(int,int,const char*,int [][MAXLEN]);
/*
这里没有编写错误处理(字串为空,空间不足等)
可以根据需求来进行处理,并返回相应的参数
*/
int lcsStr(const char *x,const char *y)
{
int m,n,i,j;
m=strlen(x);
n=strlen(y);
/*
Xi={x1,x2,x3..,xi}
Yj={y1,y2,y3..,yj}
c[i][j]用来存储Xi-1和Yj-1的最长公共子序列的长度
b[i][j]记录标志用来还原最长子序列
*/
int c[MAXLEN][MAXLEN],b[MAXLEN][MAXLEN];
memset(c,0,sizeof(c));
memset(b,0,sizeof(b));
for(i=1;i<=m;++i)
{
for(j=1;j<=n;++j)
{
/*
如果x[i-1]==y[j-1]
表示当前Xi-1跟Yj-1最长子序列等于Xi-2跟Yj-2最长子序列后面加上x[i-1](y[j-1])
长度等于Xi-2跟Yj-2最长子序列长度加1
并设置标志位b[i][j]为1
*/
if(x[i-1]==y[j-1])
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}
/*
如果x[i-1]!=y[j-1]
而且c[i-1][j]>=c[i][j-1]
表示当前Xi-1跟Yj-1最长子序列等于Xi-2跟Yj-1最长子序列
设置两者长度相等 并设置标志位b[i][j]为2
*/
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]=2;
}
/*
如果x[i-1]!=y[j-1]
而且c[i-1][j]<c[i][j-1]
表示当前Xi-1跟Yj-1最长子序列等于Xi-1跟Yj-2最长子序列
设置两者长度相等 并设置标志位b[i][j]为3
*/
else
{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
lcs(m,n,x,b);
return 0;
}
//该方法可以根据标志位还原出Xi与Yj最长子序列
void lcs(int i,int j,const char *x,int b[][MAXLEN])
{
//如果i或者j等于0 退出递归
if(0==i||0==j)
return;
/*
如果标志位b[i][j]==1
递归调用lcs(i-1,j-1,s1,sub+1,b)还原出Xi-1与Yj-1最长子序列
并在最后面加上x[i-1](y[j-1])
*/
if(1==b[i][j])
{
lcs(i-1,j-1,x,b);
printf("%c",x[i-1]);
}
/*
如果标志位b[i][j]==2
递归调用lcs(i-1,j,x,sub,b)还原出Xi-2与Yj-1最长子序列
*/
else if(2==b[i][j])
lcs(i-1,j,x,b);
/*
如果标志位b[i][j]==3
递归调用lcs(i,j-1,x,sub,b)还原出Xi-1与Yj-2最长子序列
*/
else if(3==b[i][j])
lcs(i,j-1,x,b);
else
{
printf("lcs error\n");
exit(0);
}
}
int main()
{
char x[]="ABCBDAB";
char y[]="BDCABA";
char sub[10];
lcsStr(x,y);
system("pause");
return 0;
}
动态规划:最长子序列
最新推荐文章于 2023-07-26 15:27:37 发布