最长公共子序列问题

问题描述:

最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

 

例如:X(A,B,C,B,D,A,B)

        Y(B,D,C,A,B,A)

 

那么最长公共子序列就是:B,C,B,A

算法设计:用动态规划方法解决

最长公共子序列的结构:

设X = { x1 , ... , xm },Y = { y1 , ... , yn }及它们的最长子序列Z = { z1 , ... , zk }则:

1、若 xm = yn , 则 zk = xm = yn,且Z[k-1] 是 X[m-1] 和 Y[n-1] 的最长公共子序列

2、若 xm != yn ,且 zk != xm , 则 Z 是 X[m-1] 和 Y 的最长公共子序列

3、若 xm != yn , 且 zk != yn , 则 Z 是 Y[n-1] 和 X 的最长公共子序列

子问题的递归结构:

当 i = 0 , j = 0 时 , c[i][j] = 0

当 i , j > 0 ; xi = yi 时 , c[i][j] = c[i-1][j-1] + 1

当 i , j > 0 ; xi != yi 时 , c[i][j] = max { c[i][j-1] , c[i-1][j] }

 

还是以:X(A,B,C,B,D,A,B)

          Y(B,D,C,A,B,A)  为例

看下面的图:

由上面的分析:我们得到的源代码:

 

 1 //最长公共子序列代码模板
 2 #include <iostream>
 3 using namespace std;
 4 #define N 105
 5 
 6 int dp[N+1][N+1];
 7 char str1[N],str2[N];
 8 
 9 //比较两个数的大小
10 int maxx(int a,int b){
11      if(a>b){
12            return a;
13       }
14       return b;
15 }
16 
17  
18 //函数功能:获取两个字符串的最长公共子序列的数目
19 
20 //len1:字符串1的长度
21 
22 //len2:字符串2的长度
23 
24 int LCSL(int len1,int len2){
25       int i,j;
26       int len=maxx(len1,len2);
27       for(i=0;i<=len;i++){
28            dp[i][0]=0;//y为空字符串
29           dp[0][i]=0;//x为空字符串
30      }
31 
32 
33       for(i=1;i<=len1;i++){
34            for(j=1;j<=len2;j++){
35                  if(str1[i-1]==str2[j-1]){
36                       dp[i][j]=dp[i-1][j-1]+1;
37                 }
38                  else{
39                       dp[i][j] = maxx(dp[i - 1][ j ] , dp[i][j - 1]) ; 
40                  }
41           }
42       }
43       return dp[len1][len2];
44 }
45 
46 int main(){
47       while(cin>>str1>>str2){
48            int len1=strlen(str1);//获取字符串1的长度
49         int len2=strlen(str2);//获取字符串2的长度
50         cout<<LCSL(len1,len2)<<endl;
51       }
52       return 0;
53 }
View Code

 

posted @ 2013-08-15 22:11  蛋丁  阅读(506)  评论(0编辑  收藏  举报