标签:
定义:
子序列:原序列的一部分,要求按原序列中的顺序出现,但不要求连续
问题描述:
给定两个序列X=<x1,x2,...,xm>和Y=<y1,y2,...,yn>,找出X和Y的最大长度公共子序列
求解:
步骤一:最优子结构(描述一个最长公共子序列LCS)
定义:Xi=<x1,x2,...,xi>,Yi=<y1,y2,...,yi>
假设Z=<z1,z2,...,zk>为X和Y的一个LCS,则有:
1)如果xm=yn,那么zk=xm=yn,而且Zk-1是Xm-1和Yn-1的一个LCS
2)如果xm!=yn,那么如果zk!=xm,则Z是Xm-1和Yn的一个LCS
如果zk!=yn,则Z是X和Yn-1的一个LCS
步骤二:构造递归解
定义:
c[i,j]为序列Xi和Yi的一个LCS的长度
公式:
c[i,j]=0 if i=0 or j =0
c[i,j]=c[i-1,j-1]+1 if i,j>0 and xi=yj
c[i,j]=max(c[i-1,j],c[i,j-1]) if i,j>0 and xi!=yj
步骤三:明确重叠的子问题以及真正子问题的数目
计算c[i-1,j]和c[i,j-1]都会计算c[i-1,j-1]
由递归解的形式可以直接看出,子问题的数目是Θ(mn)
步骤四:算法设计
代码如下:
int calCLS(string s1,string s2) { string::size_type m=s1.size()+1; string::size_type n=s2.size()+1; int i,j; int **c=new int*[m]; for(i=0;i<m;i++) c[i]=new int[n]; for(i=1;i<m;i++) c[i][0]=0; for(j=0;j<n;j++) c[0][j]=0; for(i=1;i<m;i++) { for(j=1;j<n;j++) if(s1[i]==s2[j]) 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[m-1][n-1]; }
标签:
原文地址:http://www.cnblogs.com/xiangzhi/p/4711781.html