• 动态规划实现最长公共子序列


    最长公共子序列的定义
      (1) 子序列

      给定两个序列X=<x 1 ,x 2 ,...,x n >和序列Z=<z 1 ,z 2 ,...,z k >,若存在X的一个严格递增下标序列<i 1 ,i 2 ,...,i k >,使得对所有j=1,2,...,k,有x ij =z j ,则称Z是X的子序列。如:Z=<B,C,D,B>是X=<A,B,C,B,D,A,B>的一个子序列,相应下标序列为<2,3,5,7>。
      (2)公共子序列
      对给定的两个序列X和Y,若序列Z既是X的的子序列,也是Y的子序列,则称Z是X和Y的 公共子序列 。如,X=<A,B,C,B,D,A,B>,Y=<B,D,C,A,B,A>,则序列<B,C,A>是X和Y的一个公共子序列。
      (3)最长公共子序列
      两个序列的长度最大的公共子序列称为它们的 最长公共子序列 。如,<B,C,A>是上面X和Y的一个公共子序列,但不是X和Y的最长公共子序列。最长公共子序列是<B,C,B,A>。怎么求最长公共子序列?
    最长公共子序列问题( Longest-Common-Subsequence,LCS )——求(两个)序列的最长公共子序列
      (1)前缀:给定一个序列X=<x 1 ,x 2 ,...,x m >,对于i=0,1,...,m, 定义X的第i个前缀为X i =<x 1 ,x 2 ,...,x i >,即前i个元素构成的子序列。如,X=<A,B,C,B,D,A,B>,则X 4 =<A,B,C,B>,X 0 =Φ。

      (2)LCS问题的最优子结构性

      定理6.2 设有序列X=<x 1 ,x 2 ,...,x m >和Y=<y 1 ,y 2 ,...,y n >,并设序列Z=<z 1 ,z 2 ,...,z k >为X和Y的任意一个LCS。

      a.若x m =y n ,则z k =x m =y n ,且Z k-1 是X m-1 和Y n-1 的一个LCS。
      b.若x m ≠y n ,则z k ≠x m 蕴含Z是X m-1 和Y的一个LCS。
      c.若x m ≠y n ,则z k ≠y n 蕴含Z是X和Y n-1 的一个LCS。

      (3)递推关系式

      记,c[i,j]为前缀序列X i 和Y j 的一个LCS的长度。则有

      

      注: 以上情况涵盖了X m 和Y n 的LCS的所有情况。

      (4)给出一个例子

      上面黄色标注的并且为左上角标记的字符连起来就是最大公共子序列,即BCBA

     1 package cn.dp;
     2 
     3 /**
     4  * 最长公共子序列问题
     5  *
     6  */
     7 
     8 public class Test2 {
     9 
    10     static int[][] result;
    11     static String str1 = "ABCBDAB";
    12     static String str2 = "BDCABA";
    13     static char[][] b;
    14     public static void main(String[] args) {
    15             
    16         result = new int[str1.length()+1][str2.length()+1];
    17         b = new char[str1.length() + 1][str2.length() + 1];
    18         LCS(str1, str2);
    19         for (int i = 0; i < str1.length()+1; i++) {
    20             for (int j = 0; j < str2.length()+1; j++) {
    21                 System.out.print(result[i][j] + " ");
    22             }
    23             System.out.println();
    24         }
    25         System.out.println("最大公共子序列的长度为:" + result[str1.length()][str2.length()]);
    26         System.out.println("最大公共子序列为:");
    27         print_LCS(str1.length(), str2.length());
    28     }
    29     
    30     /**
    31      * 求出最大公共子序列的长度  并记录构造表信息
    32      * @param str1
    33      * @param str2
    34      */
    35     static void LCS(String str1, String str2) {
    36         /*
    37          * 初始化二位数组的边界
    38          */
    39         for (int i = 0; i <= str1.length(); i++) {
    40             result[i][0] = 0;
    41         }
    42         for (int i = 0; i <= str2.length(); i++) {
    43             result[0][i] = 0;
    44         } 
    45         for (int i = 1; i <= str1.length(); i++) {
    46             for (int j = 1; j <= str2.length(); j++) {
    47                 if(str1.charAt(i - 1) == str2.charAt(j - 1)) {
    48                     result[i][j] = result[i - 1][j - 1] + 1;
    49                     b[i][j] = '↖';
    50                 } else if(result[i - 1][j] >= result[i][j-1]) {
    51                     result[i][j] = result[i - 1][j];
    52                     b[i][j] = '↑';
    53                 } else {
    54                     result[i][j] = result[i][j - 1];
    55                     b[i][j] = '←';
    56                 }
    57             }
    58         }
    59     }
    60     
    61     /**
    62      * 打印构造表信息
    63      * @param i
    64      * @param j
    65      */
    66     static void print_LCS(int i, int j) {
    67         if(i == 0 || j == 0) {
    68             return;
    69         }
    70         if(b[i][j] == '↖') {
    71             print_LCS(i-1, j-1);
    72             System.out.print(str1.charAt(i-1));
    73         } else if(b[i][j] == '↑') {
    74             print_LCS(i-1, j);
    75         } else {
    76             print_LCS(i, j-1);
    77         }
    78     }
    79 }
    动态规划实现最长公共子序列

     

  • 相关阅读:
    docker 安装mysql5.7 加my.cnf
    docker安装redis 配置文件
    私库nexus 配置
    mysql 多个字段建立唯一索引
    scm 一些记录
    tomcat 线程数、NIO配置、内存配置
    为什么简单的一个select查询都要加上事务控制
    powerdeginer report layout
    powerdesigner-连接mysql
    [转载]如何让自己变得有趣
  • 原文地址:https://www.cnblogs.com/fsmly/p/10046715.html
Copyright © 2020-2023  润新知