码迷,mamicode.com
首页 > 其他好文 > 详细

LCS的两种解法比较

时间:2015-04-22 18:45:50      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:备忘录   dp   动态   

动态规划问题一般具有两个要素:最优子结构与子问题重叠。

通常在求解LCS问题时,我们都会用到两种方法:

1. momo-ization(备忘录方法)

利用了该问题的重叠子问题特性,而重叠子问题可以使用递归直接解决


  0 A B C B D A B
0 0 0 0 0 0 0 0 0
B 0 0 1 1 1 1 1 1
D 0 0 1 1 1 2 2 2
C 0 0 1 2 2 2 2 2
A 0 1 1 2 2 2 3 2
B 0 1 2 2 3 3 3 4
A 0 1 2 2 3 3 4 4


所谓自上而下就是从下表最大处开始递归求解,最终结果为LCS(x,y,x.length,y.length);

也就是上表中从最后一格向上回溯直到哨兵的过程,在求解每个子问题之前,我们先检测一下这个子问题之前有没有算过,若果有,那么不用计算直接返回结果,如果没有,那么就计算这个子问题,之后将结果保存起来,方便下次再遇到时使用。。

时间复杂度T(n) = O(mn);

空间复杂度S = O(mn);//二维数组


[java] view plaincopy
01.public class TTBlcs { 
02.    static int[][] c = new int[100][100]; 
03.    static int NIF = 9999; 
04.    public static void main(String[] args) {         
05.        char[] x = {‘A‘,‘B‘,‘C‘,‘B‘,‘D‘,‘A‘,‘B‘}; 
06.        char[] y = {‘B‘,‘D‘,‘C‘,‘A‘,‘B‘,‘A‘}; 
07.         
08.        //TTBlcs t = new TTBlcs(); 
09.        for(int i = 0;i <= x.length;i++){//周围有一圈哨兵均为0 
10.            for(int j = 0;j <= y.length;j++) 
11.            { 
12.                c[i][j] = NIF; 
13.            } 
14.        } 
15.        System.out.print(LCS(x,y,x.length,y.length));//自上而下 
16.    } 
17.     
18.    public static int LCS(char[] x,char[] y,int i,int j){ 
19.        if(c[i][j] < NIF)//记录如果算出来便直接返回(备忘) 
20.            return c[i][j]; 
21.        if((i == 0)||(j == 0)){ 
22.            c[i][j] = 0; 
23.        } 
24.        else if(x[i-1] == y[j-1]) 
25.                c[i][j] = LCS(x,y,i-1,j-1) + 1; 
26.        else  
27.                c[i][j] = LCS(x,y,i-1,j) >= LCS(x,y,i,j-1)? LCS(x,y,i-1,j):LCS(x,y,i,j-1); 
28.        return c[i][j]; 
29.    } 
30. 
31.} 


2. 动态规划DP:

所谓自下而上,就是从下标(1,1)处开始求解的过程,不过省去了递归的过程,自下而上的构建原问题的解,首先求解最基本的情况,再从最基本的情况一部一部的向上求解,比如我要求解[2…4],那么我首先需要知道[2…2][3…4]和[2…3][4…4]的最优解,需要知道[3…4],那么首先需要知道[3…3][4…4]的最优解,所以,倒不如我们将原问题需要的解先构建出来,再慢慢向上一层一层的构建,最后组成原问题的解!。

时间复杂度T(n) = O(mn);

空间复杂度S = O(mn);//二维数组



[java] view plaincopy
01.public class BTTlcs { 
02.    static int[][] c = new int[100][100]; 
03.    public static void main(String[] args) { 
04.        char[] x = {‘A‘,‘B‘,‘C‘,‘B‘,‘D‘,‘A‘,‘B‘}; 
05.        char[] y = {‘B‘,‘D‘,‘C‘,‘A‘,‘B‘,‘A‘}; 
06.        for(int k = 0;k <= x.length;k++) 
07.        { 
08.            c[0][k] = 0; 
09.        } 
10.        for(int k = 0;k <= y.length;k++) 
11.        { 
12.            c[k][0] = 0; 
13.        } 
14.        LCS(x,y); 
15.    } 
16.     
17.    public static void LCS(char[] x,char[] y){ 
18.        for(int i = 1;i <= x.length;i++) 
19.        { 
20.            for(int j = 1;j <= y.length;j++) 
21.            { 
22.                if(x[i-1] == y[j-1]) 
23.                    c[i][j] = c[i-1][j-1] + 1; 
24.                else  
25.                    c[i][j] = c[i-1][j] >= c[i][j-1]?c[i-1][j]:c[i][j-1]; 
26.            } 
27.        } 
28.        for(int i = 0;i <= x.length;i++) 
29.        { 
30.            for(int j = 0;j<y.length;j++) 
31.            { 
32.                System.out.print(c[i][j]); 
33.            } 
34.            System.out.print("\n"); 
35.        } 
36.        System.out.print(c[x.length][y.length]); 
37.    } 
38.} 


自上而下的优点是并不需要求解每一个子问题的解,而是只求解有需要的子问题的解,缺点就是需要递归调用,函数调用浪费时间。
自下而上的优点是并不需要递归调用,每个子问题求解的速度较快,缺点每个子问题都要计算,就算这个子问题的解对原问题的解并没有任何帮助!


LCS的两种解法比较

标签:备忘录   dp   动态   

原文地址:http://8492887.blog.51cto.com/8482887/1637190

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!