【转】LCS
动态规划法
经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题。简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加。
为了节约重复求相同子问题的时间,引入一个数组,不管它们是否对最终解有用,把所有子问题的解存于该数组中,这就是动态规划法所采用的基本方法。
【问题】 求两字符序列的最长公共字符子序列
问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。
考虑最长公共子序列问题如何分解成子问题,设A=“a0,a1,…,am-1”,B=“b0,b1,…,bm-1”,并Z=“z0,z1,…,zk-1”为它们的最长公共子序列。不难证明有以下性质:
(1) 如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,…,zk-2”是“a0,a1,…,am-2”和“b0,b1,…,bn-2”的一个最长公共子序列;
(2) 如果am-1!=bn-1,则若zk-1!=am-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列;
(3) 如果am-1!=bn-1,则若zk-1!=bn-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列。
这样,在找A和B的公共子序列时,如有am-1=bn-1,则进一步解决一个子问题,找“a0,a1,…,am-2”和“b0,b1,…,bm-2”的一个最长公共子序列;如果am-1!=bn-1,则要解决两个子问题,找出“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列和找出“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列,再取两者中较长者作为A和B的最长公共子序列。
求解:
引进一个二维数组c[][],用c[i][j]记录X[i]与Y[j] 的LCS 的长度,b[i][j]记录c[i][j]是通过哪一个子问题的值求得的,以决定搜索的方向。
我们是自底向上进行递推计算,那么在计算c[i,j]之前,c[i-1][j-1],c[i-1][j]与c[i][j-1]均已计算出来。此时我们根据X[i] = Y[j]还是X[i] != Y[j],就可以计算出c[i][j]。
问题的递归式写成:

回溯输出最长公共子序列过程:

算法分析:
由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m + n)次就会遇到i = 0或j = 0的情况,此时开始返回。返回时与递归调用时方向相反,步数相同,故算法时间复杂度为Θ(m + n)。
代码:
#include <stdio.h>
#include <string.h>
#define MAXLEN 100
//x 字符串a
//y 字符串b
//m 字符串a的长度
//n 字符串b的长度
//c x[i]、y[i]对应的lcs的长度
//b 确定打印时的搜寻方向。是向上走还是向左走
void LCSLength(char *x, char *y, int m, int n, int c[][MAXLEN], int b[][MAXLEN])
{
int i, j; for(i = ; i <= m; i++)
c[i][] = ;
for(j = ; j <= n; j++)
c[][j] = ;
for(i = ; i<= m; i++)
{
for(j = ; j <= n; j++)
{
if(x[i-] == y[j-])
{
c[i][j] = c[i-][j-] + ;
b[i][j] = ;
}
else if(c[i-][j] >= c[i][j-])
{
c[i][j] = c[i-][j];
b[i][j] = ;
}
else
{
c[i][j] = c[i][j-];
b[i][j] = -;
}
}
}
} void PrintLCS(int b[][MAXLEN], char *x, int i, int j)
{
if(i == || j == )
return;
if(b[i][j] == )
{
PrintLCS(b, x, i-, j-);
printf("%c ", x[i-]);
}
else if(b[i][j] == )
PrintLCS(b, x, i-, j);
else
PrintLCS(b, x, i, j-);
} int main(int argc, char **argv)
{
char x[MAXLEN] = {"ABCBDAB"};//字符串a
char y[MAXLEN] = {"BDCABA"};//字符串b
int b[MAXLEN][MAXLEN];//
int c[MAXLEN][MAXLEN];//a[i]、b[j]对应的lcs长度
int m, n; m = strlen(x);//字符串a的长度
n = strlen(y);//字符串b的长度 LCSLength(x, y, m, n, c, b);
PrintLCS(b, x, m, n); return ;
}
转自http://blog.csdn.net/yysdsyl/article/details/4226630
【转】LCS的更多相关文章
- 我的第一篇博客----LCS学习笔记
LCS引论 在这篇博文中,博主要给大家讲一个算法----最长公共子序列(LCS)算法.我最初接触这个算法是在高中学信息学竞赛的时候.那时候花了好长时间理解这个算法.老师经常说,这种算法是母算法,即从这 ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- Hackerrank11 LCS Returns 枚举+LCS
Given two strings, a and , b find and print the total number of ways to insert a character at any p ...
- UVA 11404 Palindromic Subsequence[DP LCS 打印]
UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...
- 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题
先要搞明白:最长公共子串和最长公共子序列的区别. 最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...
- 最大公共字串LCS问题(阿里巴巴)
给定两个串,均由最小字母组成.求这两个串的最大公共字串LCS(Longest Common Substring). 使用动态规划解决. #include <iostream> #inclu ...
- LCS
/**LCS问题*/ #include <iostream>#include <string>#include <algorithm> using namespac ...
- hdu 1503, LCS variants, find a LCS, not just the length, backtrack to find LCS, no extra markup 分类: hdoj 2015-07-18 16:24 139人阅读 评论(0) 收藏
a typical variant of LCS algo. the key point here is, the dp[][] array contains enough message to de ...
- Constructing Roads In JGShining's Kingdom(HDU1025)(LCS序列的变行)
Constructing Roads In JGShining's Kingdom HDU1025 题目主要理解要用LCS进行求解! 并且一般的求法会超时!!要用二分!!! 最后蛋疼的是输出格式的注 ...
随机推荐
- MySQL存储过程-通过数据库里已存在的IP查询城市
CREATE DEFINER=`mazey`@`%` PROCEDURE `sp_find_city_by_ip`(IN `in_visitor_ip` varchar(20),OUT `out_vi ...
- 我的Android进阶之旅------>Android疯狂连连看游戏的实现之开发游戏界面(二)
连连看的游戏界面十分简单,大致可以分为两个区域: 游戏主界面区 控制按钮和数据显示区 1.开发界面布局 本程序使用一个RelativeLayout作为整体的界面布局元素,界面布局上面是一个自定义组件, ...
- (转)复习TCP/IP协议与Http协议的区别
TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据.关于TCP/IP和HTTP协议的关系,网络有一段比较容易理解的介绍:“我们在传输数据时,可以只 ...
- UVALive - 6257 K - Chemist's vows 【DFS】【BFS】【DP】
题目链接 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- Elasticsearch的几种架构(ELK,EL,EF)性能对比测试报告
Elasticsearch的几种架构性能对比测试报告 1.前言 选定了Elasticsearch作为存储的数据库,但是还需要对Elasticsearch的基础架构做一定测试,所以,将研究测试报告输出如 ...
- Effective java -- 5 枚举和注解
第三十条:用enum代替int常量enum的简单用法. enum Operation { PLUS("+") { double apply(double x, double y) ...
- js原生函数一些封装
这是一些js原生封装的函数,主要是为了兼容IE浏览器,如下 获取css样式 function getStyle(ele, prop) { if(window.getComputedStyle) { r ...
- inline-block间距解决方案
当我们将元素设为inline-block时,总是会莫名其妙出现一些间距 <!DOCTYPE html> <html> <head> <meta charset ...
- stack-铁轨问题
每辆火车都从A方向驶入车站,再从B方向驶出车站,同时它的车厢可以进行某种形式的重新组合.假设从A方向驶来的火车有n节车厢(n<1000),分别按顺序编号为1,2,...,n.假定在进入车站之前每 ...
- String类型的对象,是保存在堆里还是在栈里呢?
在Java的实现中,new出来的String对象一般是放在堆中的. 如果是 String s ="xxx"; 这种,那就是放在常量池中. JDK6将常量池放在方法区中. 方法区此时 ...