zoukankan      html  css  js  c++  java
  • 算法——动态规划篇——最长公共子序列

    问题描写叙述

         最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,假设各自是两个或多个已知序列的子序列,且是全部符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。  

        解决最长公共子序列,一种经常使用的办法,就是穷举法,组合出全部的情况,可是这样对于长序列的情况来说,是很不实际。。

    如果如今有两个序列,x[]={'A','B','C','B','D','A','B'};y[]={'B','D','C','A','B','A'};

    假设採用穷举的方式,会是下面情况

    x:A,B,C,B,D,A,B

    y:B,D,C,A,B,A

    A与B比較,一直到A与Y中出现的第一个A遇到事停止(红色部分),然后再从X序列中的B与Y中B開始比較,(绿色部分),接着这样下去,直观上看,运行这一次遍历,就是n*n的代价,要是把全部的可能都遍历一下,代价太大了。。


    仅仅有採用其它的方法了,

    动态规划:

    观察到序列求解过程中,有一定的相似度,比方说,假设我们的序列是X:A,B,C;Y:B,D,C;因为Xc=Yc,全部要往前面的两个元素看,也就是比較X:A,B;Y:B,D,因为Xb!=Yd,那么我们须要推断X:A;Y:B,D的最大序列,以及X:A,B;YB的最大序列,取两者中最大的一个,保留下来,作为X:A,B;Y:B,D的最大序列值。

    分析问题的时候一直要先从总体上来把握,体会他的总体局部的相关性,而不是孤立出来,仅仅是单纯的从元素本身来推断,那样就不好明确问题的规律。。。

    最后还是翻看了算法导论,才明确这一点,没有把握住,问题的本质。。

    最长子序列的规律:

    c[i][j]={

    0  ,i=0||j=0

    c[i-1][j-1]+1  ,i,j>0&&xi=yj

            max(c[i-1][j],c[i][j-1]),i,j>0&&xi!=yj

    }


    分析清楚问题真的非常重要。。。。把握问题的本质。。。


    代码例如以下:

    package hello.ant;
    //最长公共子序列
    public class AlogLCS {
    	public static void main(String[] args) {
    		char x[]={'A','B','C','B','D','A','B'};
    		char y[]={'B','D','C','A','B','A'};
    		
    		int c[][]=new int[x.length+1][y.length+1];
    		//////////////    ^|^               ~~               ~~~
    		/////////////      |               ~ -------            ~~~
    		//////////////     |                ~~                      ~~
    		//////////////     用0表示向上       1向左                           		2表示斜向左上
    		int flag[][]=new int[x.length+1][y.length+1];//用来控制打印的方向
    		
    		//初始化
    		for(int i=0;i<y.length+1;i++){
    			c[0][i]=0;
    		}
    		for(int i=0;i<x.length+1;i++){
    			c[i][0]=0;
    		}
    		for(int i=1;i<x.length+1;i++){
    			for(int j=1;j<y.length+1;j++){
    				if(x[i-1]==y[j-1]){
    					c[i][j]=c[i-1][j-1]+1;
    					flag[i][j]=2;
    				}else {
    					if(c[i-1][j]>=c[i][j-1]){
    						c[i][j]=c[i-1][j];
    						flag[i][j]=0;
    					}else {
    						c[i][j]=c[i][j-1];
    						flag[i][j]=1;
    					}
    				}
    			}
    		}
    		StringBuilder result=new StringBuilder();
    		display(x,flag,x.length,y.length,result);
    		System.out.println("
    *********");
    		System.out.println(result.reverse().toString());
    	}
    
    	static void display(char[] x, int[][] flag, int i, int j,StringBuilder result) {
    		if(i==0||j==0){
    			return;
    		}
    		if(flag[i][j]==2){
    			System.out.print(x[i-1]+"  ");
    			result.append(x[i-1]);
    			display(x, flag, i-1, j-1,result);
    		}else if(flag[i][j]==1){
    			display(x, flag, i, j-1,result);
    		}else if(flag[i][j]==0){
    			display(x, flag, i-1, j,result);
    		}
    	}
    }
    

    结果例如以下:

    A  B  C  B  
    *********
    BCBA


    红色部分才是真正的最长子序列。。。


  • 相关阅读:
    AngularJS Insert Update Delete Using PHP MySQL
    Simple task manager application using AngularJS PHP MySQL
    AngularJS MySQL and Bootstrap Shopping List Tutorial
    Starting out with Node.js and AngularJS
    AngularJS CRUD Example with PHP, MySQL and Material Design
    How to install KVM on Fedora 22
    Fake_AP模式下的Easy-Creds浅析
    河南公务员写古文辞职信
    AI
    政协委员:最大愿望是让小学生步行上学
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3818413.html
Copyright © 2011-2022 走看看