题目描述:

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

题目分析:

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. chip-seq数据分析中peak-calling软件-------MACS的安装

    1.下载MACS软件安装包(作者的系统为Ubuntu) 网址链接:http://liulab.dfci.harvard.edu/MACS/ 2.解压文件: tar -zxvf MACS**.tar.g ...

  2. CSS 公共样式

    global.css | reset.css(格式化样式) common.css(公共组件样式) layout.css(当前页面样式) 清除全站所有页面的浏览器默认样式,保证在初始样式在所有浏览器下一 ...

  3. solr学习笔记-开篇

    由于工作需要,近期接触了一下全文检索的相关技术,从lucenen到solr开始慢慢一路摸爬滚打,仅以此文记录自己的学习里程和记录下各种坑. 本次学习基于以下环境版本: java7,solr5.5.4( ...

  4. ui-router 父子state共享数据

    如果ui-view是嵌套的,那么在子view中,可以直接引用 $scope.$parent 即可.

  5. 玩转spring boot——websocket

    前言 QQ这类即时通讯工具多数是以桌面应用的方式存在.在没有websocket出现之前,如果开发一个网页版的即时通讯应用,则需要定时刷新页面或定时调用ajax请求,这无疑会加大服务器的负载和增加了客户 ...

  6. H5本地储存Web Storage

    一.本地存储由来的背景 由于HTML4时代Cookie的大小.格式.存储数据格式等限制,网站应用如果想在浏览器端存储用户的部分信息,那么只能借助于Cookie.但是Cookie的这些限制,也就导致了C ...

  7. 【巨杉答疑】巨杉数据库和mongodb有什么关系吗?

    哈罗,艾瑞巴蒂~巨杉答疑栏目今日上线啦! 巨杉数据库作为商业化开源软件,已经拥有大量社区用户.开源至今,大到分布式数据库原理.架构问题,小到SDB巨杉数据库的安装使用问题,大家似乎都有很多问题想要和我 ...

  8. Java 泛型在实际开发中的应用

    java泛型是对Java语言的类型系统的一种扩展,泛型的本质就是将所操作的数据类型参数化.下面我会由浅入深地介绍Java的泛型. 一:泛型出现的背景 在java代码里,你会经常发现类似下边的代码: p ...

  9. 开源自己写的图片转Ascii码图工具

    GitHub地址:https://github.com/qiangzi7723/img2Ascii 如果觉得不错可以给个star或者提出你的建议 img2Ascii,基于JS的图片转ASCII示意图. ...

  10. SQL Server Alwayson配置两个节点加共享文件夹仲裁见证

    标签:MSSQL/节点和共享文件夹多数 概述 之前讲过多数节点的仲裁配置,多数节点一般3个节点以上的奇数个节点:常见的是使用3个节点节点多了也是浪费因为Alwayson的只读路由只能利用到一个只读副本 ...