题目描述:

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

题目分析:

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实现):

 import java.util.Scanner;

 public class LCSequence {
public static void main(String[] args) {
String[] paras = getInput();
System.out.println(getLongestSubsequence(paras[0], paras[1]));
} public static String[] getInput() {
Scanner reader = new Scanner(System.in);
String[] paras = new String[2];
paras[0] = reader.nextLine();
paras[1] = reader.nextLine();
reader.close();
return paras;
} public static String[][] getGenerationMatirx(String str1, String str2) {
int[][] temp = new int[str1.length() + 1][str2.length() + 1];
String[][] flag = new String[str1.length() + 1][str2.length() + 1];
for (int i = 0; i <= str1.length(); i ++) {
temp[i][0] = 0;
}
for (int i = 0; i <= str2.length(); i ++) {
temp[0][i] = 0;
}
//迭代获取最长公共子序列的生成矩阵
for (int i = 1; i <= str1.length(); i ++) {
for (int j = 1; j <= str2.length(); j ++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
temp[i][j] = temp[i - 1][j - 1] + 1;
flag[i][j] = "left_up";
} else {
if (temp[i - 1][j] >= temp[i][j - 1]) {
temp[i][j] = temp[i - 1][j];
flag[i][j] = "up";
} else {
temp[i][j] = temp[i][j - 1];
flag[i][j] = "left";
}
}
}
}
return flag;
}
public static String getLongestSubsequence(String str1, String str2) {
String[][] flagMatrix = getGenerationMatirx(str1, str2);
String tempString = "";
for (int i = str1.length(), j = str2.length(); i > 0 && j > 0;) {
if (flagMatrix[i][j].equals("left_up")) {
tempString += str1.charAt(i - 1);
i --;
j --;
} else if (flagMatrix[i][j].equals("left")) {
j --;
} else {
i --;
}
}
return new StringBuffer(tempString).reverse().toString();
} }

运行结果:

    

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

 

华为OJ之最长公共子序列的更多相关文章

  1. 华为OJ之最长公共子串

    题目描述: 对于两个给定的字符串,给出他们的最长公共子串. 题目分析: 1,最长公共子串(LCS)实际上是最长公共子序列的一种特殊情况,相当于是求连续的最长子序列.我们今天先解决这个特殊情况,后续博文 ...

  2. CJOJ 2044 【一本通】最长公共子序列(动态规划)

    CJOJ 2044 [一本通]最长公共子序列(动态规划) Description 一个给定序列的子序列是在该序列中删去若干元素后得到的序列.确切地说,若给定序列X,则另一序列Z是X的子序列是指存在一个 ...

  3. 38-最长公共子序列(dp)

    最长公共子序列 https://www.nowcoder.com/practice/c996bbb77dd447d681ec6907ccfb488a?tpId=49&&tqId=293 ...

  4. 用python实现最长公共子序列算法(找到所有最长公共子串)

    软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...

  5. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

  6. [Data Structure] LCSs——最长公共子序列和最长公共子串

    1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...

  7. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  8. LintCode 77: 最长公共子序列

    public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...

  9. 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题

    先要搞明白:最长公共子串和最长公共子序列的区别.    最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...

随机推荐

  1. angularJS ng-change错误的解决方案

    导入文件:<script src="../../js/angular/angular-file-upload/angular-file-upload.js"></ ...

  2. html、css和js注释的规范用法

    成为专业的前端工程师!!! html注释: <!--注释内容--> css注释: //注释内容 单行注释(不推荐使用,因为有的浏览器可能不兼容,没有效果)/*注释内容*/ 多行注释(推荐使 ...

  3. 调试JDK源码时,不能查看变量的值

    前几天本来想以debug模式看一下JDK的源码,进入调试模式时才发现,根本看不到方法里面变量值的情况.为什么呢?JDK现在的版本中,编译过后,去除了里面的调试信息.解决办法是,编译那些类,使其带有调试 ...

  4. Canvas学习系列一:初识canvas

    最近你开始在学习canvas,打算把学习canvas的整个学习过程当中的一些笔记与总结记录下来,如有什么不足之处还请大神们多多指出. 1. 认识canvas Canvas元素的出现,可以说开启的Web ...

  5. vue-router单页应用简单示例(二)

    我们先来理一下思路. 图1:main.js 引入vue,App.vue,router/index.js文件 声明要渲染的Id为app,将App.vue中的模版渲染到入口界面(就是打开localhost ...

  6. 静态库 .a 转成共享库 .so

    .a 是有一系列 .o 文件通过 ar 程序打包在一起的静态库,要把它转成动态库只需先解开,生成一堆 .o 文件,再通过编译器(比如 gcc 或 ifort,视具体情况而定)编成动态库即可. ar - ...

  7. module.exports与exports,export和export default

    还在为module.exports.exports.export和export default,import和require区别与联系发愁吗,这一篇基本就够了! 一.首先搞清楚一个基本问题: modu ...

  8. chrome谷歌浏览器-DevTool开发者工具-详细总结

    目录: 一.概述 1.官方文档 2.打开方法: 3.前言: 二.九个模块: 1.设备模式Device Mode 2.元素面板Elements 3.控制台面板Console 4.源代码面板Sources ...

  9. phpcms和php格式化时间戳

    用PHPCMS V9 建站时,经常会用到时间标签,它是通用标签调用-日期时间格式化,适用全站. 一.日期时间格式化显示: a\标准型:{date('Y-m-d H:i:s', $rs['inputti ...

  10. php导入csv文件

    <?php /** * Created by PhpStorm. * User: hanks * Date: 2017/4/30 * Time: 13:24 */ include 'header ...