我的第一篇博客----LCS学习笔记
LCS引论
在这篇博文中,博主要给大家讲一个算法----最长公共子序列(LCS)算法。我最初接触这个算法是在高中学信息学竞赛的时候。那时候花了好长时间理解这个算法。老师经常说,这种算法是母算法,即从这种算法中能衍生出许许多多的子算法。是的,博主在大二的算法导论考试中,就被LCS衍生的子算法“坑”了。当时一道动态规划题目,大概是要写一列书中放置书架的问题。博主联想到了LCS,但是最后还是只是用暴力求解法解出了那道题目,甚是遗憾。在这里,我也对此算法做一个详解。
优化子结构
首先,我们来看优化子结构:
设X=(x 1 , ..., x m ) 、Y=(y 1 , ..., y n ) 是两个序列,Z=(z 1 , ..., z k ) 是X 与Y 的LCS ,我们有:
⑴ 如果xm =yn, 则zk =xm = yn , Zk-1 是Xm-1 和Yn-1 的LCS , 即 :
LCS XY = LCS X m-1 Y n-1 + <xm =yn >.
⑵ 如果xm ≠ yn , 且zk≠ xm , 则Z 是X m-1 和Y 的
LCS , 即 LCS XY = LCS X m-1 Y
⑶ 如果xm ≠ yn ,且zk≠ yn ,则Z 是X 与Y n-1 的LCS ,即 :
LCS XY = LCS XY n-1
构造C[m,n]数组表示xm 、yn 的LCS长度,因此,求得X和Y的优化解结构的递归方程为:
C[i, j] = 0 if i=0 或 j=0
C[i, j] = C[i-1, j-1] + 1 if i, j>0 且 x i = y j
C[i, j] = Max(C[i, j-1], C[i-1, j]) if i, j>0 且 x i ≠ y j
在存储LCS的时候,我们根据已经构造好的B[m,n]来寻找全部的LCS。
如果B[m,n]=0,说明X和Y当前比对的字符相同,因此我们把X和Y都向前一个字符,再进行比对。
如果B[m,n]=1,说明xm ≠ yn , 且zk≠ xm ,此时我们只用把X向前移一位,再进行比对。
如果B[m,n]=3,说明xm ≠ yn ,且zk≠ yn,此时我们需要把Y向前移动一位,再进行比对。
如果B[m,n]=2,说明c[i - 1][j] = c[i][j - 1],我们需要将两个字符串依次向前移动一位,进行比对
关键的数据结构及简单说明
C[m,n]: C[i,j] 是X i 与Y j 的LCS 的长度;
B[m,n]: B[i,j] 是指针 ,指向计算C[i,j] 时所选择的子问题的优化解所对应的C 表的表项。通俗的说,B[m,n]记录的是轨迹;
public static String[] Log:存储全部LCS字符串;
public static char[] lcs:字符数组,存储
TreeSet<String> tree = new TreeSet<String>():将LCS数组存入Tree集合中,供打印使用。
示例程序
package test;
import java.util.Scanner;
import java.util.TreeSet;
public class LCS {
public static StringBuffer X;
public static StringBuffer Y;
public static int m;
public static int n;
public static int len;
public static int[][] b;
public static int[][] c;
public static String[] Log;
public static char[] lcs;
public final static int MAX = 100;
public static int boardlen;
public static void main(String[] args) {
Log = new String[MAX];
LCS lcs = new LCS();
Scanner in = new Scanner(System.in);
System.out.println("string X:");
X = new StringBuffer(in.next());
System.out.println("string Y:");
Y = new StringBuffer(in.next());
lcs_length();
System.out.println("LCS:");
store_lcs(m, n, len);
PrintLCS();
X.setLength(0);
Y.setLength(0);
in.close();
}
public static void lcs_length() {
m = X.length();
n = Y.length();
lcs = new char[m + 1];
boardlen = 0;
c = new int[m + 1][n + 1];
b = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++)
c[i][0] = 0;
for (int j = 0; j <= n; j++)
c[0][j] = 0;
for (int i = 1; i <= m; i++){
for (int j = 1; j <= n; j++) {
if (X.charAt(i - 1) == Y.charAt(j - 1)) {
c[i][j] = c[i - 1][j - 1] + 1;
b[i][j] = 0;
} else if (c[i - 1][j] > c[i][j - 1]) {
c[i][j] = c[i - 1][j];
b[i][j] = 1;
} else if (c[i - 1][j] == c[i][j - 1]) {
c[i][j] = c[i - 1][j];
b[i][j] = 2;
} else {
c[i][j] = c[i][j - 1];
b[i][j] = 3;
}
}
}
len = c[m][n];
}
public static void store_lcs(int m, int n, int Len) {
if (m == 0 || n == 0) {
Log[boardlen] = new String(lcs);
boardlen++;
} else {
if (b[m][n] == 0) {
lcs[Len] = X.charAt(m - 1);
Len--;
store_lcs(m - 1, n - 1, Len);
} else if (b[m][n] == 3) {
store_lcs(m, n - 1, Len);
} else if (b[m][n] == 1) {
store_lcs(m - 1, n, Len);
} else {
store_lcs(m, n - 1, Len);
store_lcs(m - 1, n, Len);
}
}
}
public static void PrintLCS() {
TreeSet<String> tree = new TreeSet<String>();
for (int i = 0; i <boardlen; i++) {
tree.add(Log[i]);
}
String[] string = new String[tree.size()];
for (int i = 0; i < string.length; i++) {
string[i] = tree.pollFirst();
System.out.println(string[i]);
}
}
public void printit() {
for (int i = 0; i < Log.length; i++) {
if (Log[i] != null) {
System.out.println(Log[i]);
}
}
}
}
后序
程序经本人测试,能够运行出正确结果。以上仅供大家学习交流,转载请注明出处。
我的第一篇博客----LCS学习笔记的更多相关文章
- 第一篇博客:Hello World
2016年10月10日,双十,好日子,决定开始写第一篇博客,标题想了会,就叫Hello World 吧,哈哈^_^. 首先感谢博客园的管理们能批准我的申请,记得在14年的时候申请过一次,竟然没申请通过 ...
- 我的第一篇博客 ——【ToDoList】小程序开发
我是一只即将大四的大三狗,这是我的第一篇博客,说来惭愧.今年1月份,学校放寒假的时候开始自学的IOS,放假的时候比较起劲,看了一堆Object-C的视频,然后照着中英文对照的IOS基础开发教程,做了两 ...
- Hello World -- 第一篇博客
今年注定是不寻常的一年,因为技术,接触了许多大牛.通过一篇篇博文,看到了大牛们勤奋好学.孜孜不倦的精神,于是决定也开个博客,向大牛学习. 博客开了,写点什么呢?奈何肚子里墨水不多,吐出来也多是白沫,不 ...
- “Hello, my first blog”------第一篇博客的仪式感
本人在校大学生一枚,开通博客,主要是想记录自己的学习过程,分享自己的学习经历.记得大一的时候,很多不懂的操作和知识,都是在博客上找到了相应的解决办法.但比较讽刺的是,很多时候,曾经解决了的问题,当再次 ...
- C博客作业00—我的第一篇博客
C博客作业00-我的第一篇博客 1. 你对网络专业或者计算机专业了解是怎样? 泛泛了解 - 原先只知道网络工程隶属于计算机工程学院,与院中其他专业一样,同样都需要学习大量的计算机基础知识,然后再分支学 ...
- Hello World -- 第一篇博客 -- 活着的意义
今年注定是不寻常的一年,因为技术,接触了许多大牛.通过一篇篇博文,看到了大牛们勤奋好学.孜孜不倦的精神,于是决定也开个博客,向大牛学习. 博客开了,写点什么呢?奈何肚子里墨水不多,吐出来也多是白沫,不 ...
- Youcans 的第一篇博客
这是我的第一篇博客. 今后我会将我的学习心得和总结在这里发布,与大家共享,共勉.
- 我的第一篇博客blog,笑哭
我的第一篇博客blog Markdown学习 一级标题:#加一个空格 加 文字, 二级标题:加2个##以此类推 字体 粗体:hello world!字体前有二个星号,字体后有二个星号 斜体:hello ...
- 第一篇博客:HTML:background的使用
开篇 我是一名程序员小白,这是我写的第一篇博客,在学习的路上难免会遇到难以解决的问题,我将会在这里写下我遇到的问题并附上解决方法 希望可以对各位有所帮助!! 我们在html中经常会遇到这样的问题 例如 ...
随机推荐
- 从Maya中把模型搬运至网页的过程
虽然利用threejs来在网页中渲染3d模型不是第一次折腾了,但是还是遇到了各种问题.总结下我所遇到的问题,希望能给正在使用threejs的小伙伴一个帮助. 一.所使用的软件与开发环境 Maya201 ...
- 【css3笔记】---- 渐变的秘密
<CSS揭秘>这本书非常不错,充满了干货和惊喜.以下主要是关于使用渐变做出来的一些效果的笔记.请用最新的现代浏览器观看. 首先要回顾下一个css语句: linear-gradient([ ...
- 基于Quick-cocos2d-x的资源更新方案 二
写在前面 又是12点半了,对于一个程序员来说,这是一个黄金时间,精力旺盛,我想,是最适合整理和分享一些思路的时候了. 自从上次写了 基于Quick-cocos2d-x的资源更新方案 同样可见quick ...
- Android Secret Code
我们很多人应该都做过这样的操作,打开拨号键盘输入*#*#4636#*#*等字符就会弹出一个界面显示手机相关的一些信息,这个功能在Android中被称为android secret code,除了这些系 ...
- php中使用fsockopen实现异步请求
php执行一段程序,有可能几毫秒就执行完毕,也有可能耗时较长.例如,用户下单这个事件,如果调用了些第三方服务进行发邮件.短信.推送等通知,可能导致前端一直在等待.而有的时候,我们并不关心这些耗时脚本的 ...
- 学习WCF入门的第一个实例
一.概述 WCF说白了就是一个基于终结点的通信手段!就是Service端提供一定的功能实现,然后暴露出一个或多个终结点,Client端调用Service端的功能(可以理解为调用一个函数),那么Clie ...
- APP测试点总结(功能,交互,死机崩溃状态分析,容易出错的检查点)
APP测试点总结(功能,交互,死机崩溃状态分析,容易出错的检查点) 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近涉足APP端测试,常见检查点总结如下: 一.业务方面: 1. 注册( ...
- ES6 新特性
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...
- Javascript刷题 》数组求和
计算给定数组 arr 中所有元素的总和 输入描述: 数组中的元素均为 Number 类型 输入例子: sum([ 1, 2, 3, 4 ]) 输出例子: 10 解题方法 1.定义一个变量,将前面的和后 ...
- nhibernate连接11g数据库
我框架的数据映射用 nhibernate连接多数据库,这次又增加了oracle11g,负责开发的同事始终连接不上,悲催的sharepoint调试是在不方便... 下面描述下问题的解决,细节问题有3个: ...