题目描述:

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

题目分析:

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. 平时常用的一些java方法,请留意

    平时常用的一些java方法,请留意. package com.util; import java.io.BufferedInputStream; import java.io.BufferedWrit ...

  2. python+requests+unittest API接口测试

    黑熊再网上查找了下接口测试相关的资料,大都重点是以数据驱动的形式,见用例维护在文本或表格中,而没有说明怎么样去生成想要的用例, 问题: 测试接口时,比如参数a,b,c,我要先测a参数,有(不传,为空, ...

  3. (转)C++——std::string类的引用计数

    1.概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是否还记得?在你还在上学的时候,你的父母要你不要看电视,而去复习功课,于是你把自己关在房间里 ...

  4. CSS 公共样式

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

  5. Unity3D 骨骼动画原理学习笔记

    最近研究了一下游戏中模型的骨骼动画的原理,做一个学习笔记,便于大家共同学习探讨. ps:最近改bug改的要死要活,博客写的吭哧吭哧的~ 首先列出学习参考的前人的文章,本文较多的参考了其中的表述: 1. ...

  6. 通过ajax前端后台交互/登录页和注册页前端后台交互详解/前端后台交互基础应用/几个后台函数的基础应用/php文件函数基础应用/php字符传函数基础应用/php数组函数基础应用

      前  言  PHP     学习了好久的PHP,今天做一个可以后台交互的登录页和注册页,没做什么判断,简单的了解一下. 具体的内容分析如下: ① PHP中的数据传输-->>由注册页传输 ...

  7. Bash命令行编辑

    1.Readline库和命令行编辑 bash shell提供了两个内置编辑器:emacs和vi,利用它们可以以交互模式对命令行列表进行编辑,这项特性是通过Readline库的软件包实现的.当使用命令行 ...

  8. Java——面向对象基础

    Java继承 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类具有父类的各种属性和方法,或子类从父类继承方法,使得子类具 ...

  9. Github站点英文翻译

    1.Github首页 Pull requests  Issues Gist 请求 问题 要点 ----------------------------------------------------- ...

  10. Django 模型和数据库 总结

    模型和数据库 模型 首先我们在创建一个model的时候,这个类都是继承自 django.db.models.Model, 各种Model Field类型 AutoField,自动增长的IntegerF ...