看了一下介绍,感觉还是挺简单的!!
1.A和B的公共子序列中长度最长的(包含元素最多的)叫做A和B的公共子序列。
比如序列1,3,5,4,2,6,8,7和序列1,4,8,6,7,5。它们的最长公共子序列是:
1,4,8,7
1,4,6,7
2.考虑最长公共子序列的最优子结构
(1) Ax = By
那么它们的最长公共子序列的最后一项一定是这个元素!
(2) Ax ≠ By
.1如果最长公共子序列的最后一项≠ Ax,则最长公共子序列肯定是Ax-1与By的;
.2如果最长公共子序列的最后一项≠ By,则最长公共子序列肯定是By-1与Ax的;
.3求出1与2中的最长公共子序列
算法伪代码:
LCS-LENGTH(X,Y)
1. m<-length[X]
2. n<-length[Y]
3. for i<-1 to m
4. do c[i,0]<-0 //这里的c表示子序列Xi,Yj的公共子序列LCS的长度
5. for j<-0 to n
6. do c[0,j]<-0
7. for i<-1 to m
8. do for j<-1 to n
9. do if Xi=Yj
10. then c[i,j]<-c[i-1,j-1]+1
11. else if c[i-1,j] >=c[i,j-1]
12. then c[i,j]<-c[i-1,j]
13. else c[i,j]<-c[i,j-1]
14. return c
接下来要构造一个最优解
PRITN-LCS(c,X,Y,i,j)
1. if i=0 or j=0
2. then return
3. if Xi=Yj
4. then PRINT-LCS(c,X,Y,i-1,j-1)
5. print Xi
6. elseif c[i-1,j] >= c[i,j-1]
7. then PRINT-LCS(c,X,Y,i-1,j)
8. else PRINT-LCS(c,X,Y,i,j-1)
C++:
lcs.h
#define _lcs_h
#include<iostream>
using namespace std;
template<typename Iterator>
int *lcslength(Iterator x,Iterator y,int m,int n){
int *c=new int[(m+1)*(n+1)],i,j;
for(i=1;i<=m;i++)
c[i*(n+1)]=0;
for(j=0;j<=n;j++)
c[j]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
if(*(x+i-1)==*(y+j-1))
c[i*(n+1)+j]=c[(i-1)*(n+1)+j-1]+1;
else if(c[(i-1)*(n+1)+j]>=c[i*(n+1)+j-1])//其中之所以有n+1这个步骤原因就是这里i,j是相加的,所以需要过n+1的距离才能去到二维表的下一行
c[i*(n+1)+j]=c[(i-1)*(n+1)+j];
else
c[i*(n+1)+j]=c[i*(n+1)+j-1];
return c;
}
template<typename Iterator>
void printlcs(int *c,int n,Iterator x,Iterator y,int i,int j){
if(i==0||j==0)
return;
if(*(x+i-1)=*(y+j-1)){
printlcs(c,n,x,y,i-1,j-1);
cout<<*(x+i-1)<<" ";
}else if (c[(i-1)*(n+1)+j]>=c[i*(n+1)+j-1])
printlcs(c,n,x,y,i-1,j);
else
printlcs(c,n,x,y,i,j-1);
}
main.cpp
#include"lcs.h"
int main(){
int *c,a[]={389,207,155,300,299,170,158,65},
b[]={389,300,299,207,170,158,155,65};
c=lcslength(a,b,8,8);//8表示数组元素个数
printlcs(c,8,a,b,8,8);
cout<<endl;
delete []c;
}
输出结果:
JAVA:
Lcs.java
package Jamin;
public class Lcs {
public static int[][] Lcslength(Object[] x,Object[] y){
int m=x.length,n=y.length,i,j;
int[][] c=new int[m+1][n+1];
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(x[i-1].equals(y[j-1]))
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;
}
public static void printlcs(int [][] c,Object[] x,Object[] y,int i,int j) {
if(i==0||j==0)
return;
if(x[i-1].equals(y[j-1])) {
printlcs(c,x,y,i-1,j-1);
System.out.print(x[i-1]+" ");
}else if(c[i-1][j]>=c[i][j-1])
printlcs(c,x,y,i-1,j);
else
printlcs(c,x,y,i,j-1);
}
}
Test.java
package Jamin;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Character[] x= {'A','C','C','G','F'},
y= {'A','C','G','F'};
Integer[] a= {389,207,155,300,299,170,158,65},
b= {389,300,299,207,170,158,155,65};
int[][] c;
c=Lcs.Lcslength(x, y);
Lcs.printlcs(c, x, y, 5, 4);
System.out.println();
c=Lcs.Lcslength(a, b);
Lcs.printlcs(c, a, b, 8, 8);
System.out.println();
}
}
输出结果:
A C G F
389 300 299 170 158 65