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


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


  • 相关阅读:
    视频直播点播平台EasyDSS浏览器控制台报”命名重复“错误解决办法
    视频直播点播平台EasyDSS登录页如何实现插入产品广告位?
    视频直播点播平台EasyDSS系统如何将数据库迁移到Mysql数据库?
    视频直播点播系统EasyDSS如何将已存储的视频文件进行迁移?
    人工智能正在推动“硅”复兴
    人工智能如何重新定义云计算技术并提高业务效率
    《Nature》子刊:不仅是语言,机器翻译还能把脑波「翻译」成文字
    一文读懂机器阅读理解
    大数据算法应用的测试发展之路
    从800个GPU训练几十天到单个GPU几小时,看神经架构搜索如何进化
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3818413.html
Copyright © 2011-2022 走看看