实验二 动态规划算法 最长公共子序列问题

 基本题一:最长公共子序列问题

一、实验目的与要求

1、熟悉最长公共子序列问题的算法;

2、初步掌握动态规划算法;

二、实验题

    若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={BCDB}是序列X={ABCBDAB}的子序列,相应的递增下标序列为{2357}

给定2个序列XY,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列XY的公共子序列。

给定2个序列X={x1,x2,…,xm}Y={y1,y2,…,yn},找出XY的最长公共子序列。

 

三、实验提示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
include  "stdlib.h"
#include "string.h"
  
void  LCSLength( char  *x , char  *y,intm, int  n,  int  **c,  int  **b)
{
        inti ,j;
        for  (i = 1; i<= m; i++) c[i][0] = 0;
        for  (i = 1; i<= n; i++) c[0][i] = 0;
        for  (i = 1; i<= m; i++)
           for  (j = 1; j <= n; j++)
           {
             if  (x[i]==y[j])
             {
                  c[i][j]=c[i-1][j-1]+1;
                  b[i][j]=1;
             }
             else  if  (c[i-1][j]>=c[i][j-1])
             {
                  c[i][j]=c[i-1][j];
                  b[i][j]=2;
             }
             else
             {    c[i][j]=c[i][j-1];
                  b[i][j]=3;
             }
          }
}
void  LCS(inti , int  j,  char  *x , int  **b)
{
       if  (i ==0 || j==0)  return ;
       if  (b[i][j]== 1)
       {
            LCS(i-1,j-1,x,b);
            printf ( "%c" ,x[i]);
       }
       else  if  (b[i][j]== 2)
            LCS(i-1,j,x,b);
       else  LCS(i,j-1,x,b);
}


四、题目分析

       在求最长公共子序列中,我们可以看出如下规律:

设序列X={x1,x2,&hellip;,xm}Y={y1,y2,&hellip;,yn}的最长公共子序列为Z={z1,z2,&hellip;,zk} ,则

   (1)xm=yn,则zk=xm=yn,且zk-1xm-1yn-1的最长公共子序列。

 

   (2)xm&ne;ynzk&ne;xm,则Zxm-1Y的最长公共子序列。(即:ZX序列中前m个元素所组成的序列与Y序列的最长公共子序列)

 

   (3)xm&ne;ynzk&ne;yn,则ZXyn-1的最长公共子序列。(即:ZY序列中前n个元素所组成的序列与X序列的最长公共子序列)

 

由上面三个条件可得如下公式:

C[][]用来记录最长公共子序列的长度,则:

c[i][j] = <1> 0;                   (ij = 0)

 

<2> c[i-1][j-1] + 1;        (ij > 0  Xi = Yj)(即第iX序列元素与第jY元素相等)

 

<3> max(c[i][j-1] , c[i-1][j])       (ij > 0  Xi != Yj)(当XiYj不等时,取两个式子的最大值,若两者相等则默认取第一个)

 

五,源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
importjava.util.*;
import  java.io.*;
  
public  class  LCS
{
     public  static  void  main(String[] args) {  
         String s1 =  "ABCBDAB" ;  
         String s2 =  "BDCABA" ;  
         LCS cms =  new  LCS();  
         String[] x = cms.init(s1);  
         String[] y = cms.init(s2);  
         int [][] b =  new  int [x.length][y.length];  
  
         System.out.println( "最大子序列的长度为:" +lcsLength(x, y, b));  
         System.out.println( "最大子序列为:" );  
         lcs(x.length- 1 , y.length- 1 , x, b);
    
     public  static  void  lcs(inti,  int  j, String[] x,  int [][] b) {  
         if  (i ==  0  || j ==  0 )  
             return ;  
         if  (b[i][j] ==  1 ) {  
             lcs(i -  1 , j -  1 , x, b);  
             System.out.print(x[i]+ "  " );  
         else  if  (b[i][j] ==  2 )  
             lcs(i -  1 , j, x, b);  
     else
         lcs(i, j -  1 , x, b);  
     }  
  
  
     private  String[] init(String str){  
         String temp = str;  
         String[] s = temp.split( "" );  
         return  s;  
    }
  
    public  static  intlcsLength(String[] x, String[] y,  int [][] b) {  
         int  m = x.length -  1 ;  
         int  n = y.length -  1 ;  
  
         int [][] c =  new  int [m +  1 ][n +  1 ];  
  
         for  (inti =  1 ; i<= m; i++){  
             c[i][ 0 ] =  0 ;  
         }  
         for  (inti =  1 ; i<= n; i++)  
             c[ 0 ][i] =  0 ;  
  
  
         for  (inti =  1 ; i<= m; i++) {  
             for  ( int  j =  1 ; j <= n; j++) {  
                 if  (x[i].equals(y[j])) {  
                     c[i][j] = c[i -  1 ][j -  1 ] +  1 ;  
                     b[i][j] =  1 ;  
                 else  if  (c[i -  1 ][j] >= c[i][j -  1 ]) {  
                     c[i][j] = c[i -  1 ][j];  
                     b[i][j] =  2 ;   
                 else  {  
                     c[i][j] = c[i][j -  1 ];  
                     b[i][j] =  3 ;  
                 }  
             }  
         }  
             return  c[m][n];  
     }  
}


 

结果:

 



本文转自 梦朝思夕 51CTO博客,原文链接:http://blog.51cto.com/qiangmzsx/824842


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值