zoukankan      html  css  js  c++  java
  • 华为OJ之最长公共子序列

    题目描述:

    对于两个给定的字符串,给出他们的最长公共子序列。

    题目分析:

    1,在之前的博文(http://www.cnblogs.com/yonguo123/p/6711360.html)中我们讨论了最长公共子串的问题,当时也指出最长公共子串其实就是最长公共子序列的一种特殊情况,那么今天我们就来一起研究一下最长公共子序列的求解;

    2,最长公共子序列的定义这里不再赘述,和之前的最长公共子串一样,我们这次仍然采用动态规划和回溯的思想来解决;

    3,我们假设输入为str1, str2, 首先来通过动态规划获取最大最序列的长度:

       3-1,构建一个二维数组tempMatrix,维度为(str1.length + 1), (str2.length + 1);

         3-2,temp[i][j]的含义:str1.subString(0, i)和str2.subString(0, j)的最长公共子序列(注意理解这个数组的含义)的长度;

         3-3,显然temp[i][j] == 0, 当i == 0 || j == 0;

         3-4,否则,当 str1.charAt(i - 1) == str2.charAt(j - 1)时,temp[i][j] = temp[i - 1][j - 1] + 1, 否则temp[i][j] == max{temp[i, j - 1], temp[i - 1, j]}(具体原因大家自己思考一下,可以从新加入的两个尾字符是否会出现在新的LCS中来思考);

    4,已经构建好了tempMatix矩阵,实际上tempMatrix[str1.length][str2.length]就是LCS的长度了,而且tempMatrix也保存了必要的回溯信息,下面我们继续构建一个String[][] flagMatrix = new String[str1.length][str2.length], 规则如下:

      

      可能会有同学对这个左上,上,左的取值有疑问,请看下面这张回溯图:

      

      实际上回溯时具体的方向与我们对于坐标的选取是有关系的,所以大家在写代码之前,应该先把坐标方向规定好。之后的工作就是利用flagMatrix来逐步回溯,详细的实现细节见代码。

    5,如果还有其它更好的想法,欢迎大家与我交流^-^

    具体代码(Java实现):

     1 import java.util.Scanner;
     2 
     3 public class LCSequence {
     4     public static void main(String[] args) {
     5         String[] paras = getInput();
     6         System.out.println(getLongestSubsequence(paras[0], paras[1]));
     7     }
     8     
     9     public static String[] getInput() {
    10         Scanner reader = new Scanner(System.in);
    11         String[] paras = new String[2];
    12         paras[0] = reader.nextLine();
    13         paras[1] = reader.nextLine();
    14         reader.close();
    15         return paras;
    16     }
    17     
    18     public static String[][] getGenerationMatirx(String str1, String str2) {
    19         int[][] temp = new int[str1.length() + 1][str2.length() + 1];
    20         String[][] flag = new String[str1.length() + 1][str2.length() + 1];
    21         for (int i = 0; i <= str1.length(); i ++) {
    22             temp[i][0] = 0;
    23         }
    24         for (int i = 0; i <= str2.length(); i ++) {
    25             temp[0][i] = 0;
    26         }
    27         //迭代获取最长公共子序列的生成矩阵
    28         for (int i = 1; i <= str1.length(); i ++) {
    29             for (int j = 1; j <= str2.length(); j ++) {
    30                 if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
    31                     temp[i][j] = temp[i - 1][j - 1] + 1;
    32                     flag[i][j] = "left_up";
    33                 } else {
    34                     if (temp[i - 1][j] >= temp[i][j - 1]) {
    35                         temp[i][j] = temp[i - 1][j];
    36                         flag[i][j] = "up";
    37                     } else {
    38                         temp[i][j] = temp[i][j - 1];
    39                         flag[i][j] = "left";
    40                     }
    41                 }
    42             }
    43         }
    44         return flag;
    45     }
    46     public static String getLongestSubsequence(String str1, String str2) {
    47         String[][] flagMatrix = getGenerationMatirx(str1, str2);
    48         String tempString = "";
    49         for (int i = str1.length(), j = str2.length(); i > 0 && j > 0;) {
    50                 if (flagMatrix[i][j].equals("left_up")) {
    51                     tempString += str1.charAt(i - 1);
    52                     i --;
    53                     j --;
    54                 } else if (flagMatrix[i][j].equals("left")) {
    55                     j --;
    56                 } else {
    57                     i --;
    58                 }
    59         }
    60         return new StringBuffer(tempString).reverse().toString();
    61     }
    62 
    63 }

    运行结果:

        

      这里需要注意一点,因为LCS可能不止一个,所以对于flagMatrix的赋值其实不止一种情况,代码34行中大于或者大于等于都可以,但是可能会输出不同的结果。

     

  • 相关阅读:
    OA 办公自动化系统:权限管理模块的实现原理思路
    Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/hibernate/annotations/Entity
    Spring —— 三种配置数据源的方式:spring内置、c3p0、dbcp
    使用JdbcTemplate简化JDBC操作 实现数据库操作
    Spring aop——前置增强和后置增强 使用注解Aspect和非侵入式配置
    ( 解压缩版 免安装版 或 zip版 )如何修改mysql5.6.24 字符编码
    手机开发插件安装Xamarin
    JQuery对象转dom ,dom转jQuery
    读取XML
    【Android】完善Android学习(六:API 4.0)
  • 原文地址:https://www.cnblogs.com/yonguo123/p/6720871.html
Copyright © 2011-2022 走看看