• 华为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行中大于或者大于等于都可以,但是可能会输出不同的结果。

     

  • 相关阅读:
    线性代数思维导图——3.向量
    微分中值定理的基础题型总结
    构造函数
    Python课程笔记(七)
    0241. Different Ways to Add Parentheses (M)
    0014. Longest Common Prefix (E)
    0013. Roman to Integer (E)
    0011. Container With Most Water (M)
    0010. Regular Expression Matching (H)
    0012. Integer to Roman (M)
  • 原文地址:https://www.cnblogs.com/yonguo123/p/6720871.html
Copyright © 2020-2023  润新知