最长公共子序列

一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X=,则另一序列Z=是X的 子序列是指存在一个严格递增的下标序列 ,使得对于所有j=1,2,…,k有
a) 最长公共子序列的结构 若用穷举搜索法,耗时太长,算法需要指数时间。 易证最长公共子序列问题也有最优子结构性质 设序列X=和Y=的一个最长公共子序列Z=,则: i. 若xm=yn,则zk=xm=yn且Zk­1是Xm­1和Yn­1的最长公共子序列; ii. 若xm≠yn且zk≠xm ,则Z是Xm­1和Y的最长公共子序列; iii. 若xm≠yn且zk≠yn ,则Z是X和Yn­1的最长公共子序列。 其中Xm­1=,Yn­1=,Zk­1=。 最长公共子序列问题具有最优子结构性质。 b) 子问题的递归结构 由最长公共子序列问题的最优子结构性质可知,要找出X=和Y=的最长公共子序列,可按以下方式递归地进行:当 xm=yn时,找出Xm­1和Yn­1的最长公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一个最长公共子序列。 当xm≠yn时,必须解两个子问题,即找出Xm­1和Y的一个最长公共子序列及X和Yn­1的一个最长公共子序列。这两 个公共子序列中较长者即为X和Y的一个最长公共子序列。 由此递归结构容易看到最长公共子序列问题具有子问题重叠性质。例如,在计算X和Y的最长公共子序列时,可能要 计算出X和Yn­1及Xm­1和Y的最长公共子序列。而这两个子问题都包含一个公共子问题,即计算Xm­1和Yn­1的最长 公共子序列。 我们来建立子问题的最优值的递归关系。用c[i,j]记录序列Xi和Yj的最长公共子序列的长度。其中Xi=,Yj=。当i=0或 j=0时,空序列是Xi和Yj的最长公共子序列,故c[i,j]=0。建立递归关系如下: c) 计算最优值 由于在所考虑的子问题空间中,总共只有θ(m*n)个不同的子问题,因此,用动态规划算法自底向上地计算最优值能 提高算法的效率。 计算最长公共子序列长度的动态规划算法LCS_LENGTH(X,Y)以序列X=和Y=作为输入。输出两个数组c[0…m ,0…n] 和b[1…m ,1…n]。其中c[i,j]存储Xi与Yj的最长公共子序列的长度,b[i,j]记录指示c[i,j]的值是由哪一个子问题的解达到 的,这在构造最长公共子序列时要用到。最后,X和Y的最长公共子序列的长度记录于c[m,n]中。 程序如下:

#include<stdio.h> #include<string.h> 
int lcs_length(char x[], char y[]); 
int main() {char x[100],y[100];
 int len; while(1) {scanf("%s%s",x,y); 
 if(x[0]=='0') //约定第一个字符串以‘0’开始表示结束 break; len=lcs_length(x,y); printf("%d\n",len); }}int lcs_length(char x[], char y[] ) {int m,n,i,j,l[100][100];
  m=strlen(x); 
  n=strlen(y); 
  for(i=0;i<m+1;i++) l[i][0]=0; 
  for(j=0;j<n+1;j++) l[0][j]=0;
   for(i=1;i<=m;i++) for(j=1;j<=n;j++) if(x[i‐1]==y[j‐1]) //i,j从1开始,但字符串是从0开始 l[i][j]=l[i‐1][j‐1]+1; else if(l[i][j‐1]>l[i‐1][j]) l[i][j]=l[i][j‐1]; else l[i][j]=l[i‐1][j]; return l[m][n]; }
上一篇:封装继承多态


下一篇:封装