一、最长公共子序列

  经典的动态规划问题,大概的陈述如下:

  给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个序列中的部分(不要求连续),这个就叫做公共子序列,然后最长公共子序列自然就是所有的子序列中最长的啦。

  既然是动态规划,难点肯定是在转移方程那了。首先我们用一张网上流传的图:

  我个人觉得这张图最好的阐述了这个问题的解法。下面说一下我的理解:首先我们要考虑怎么表示LCS中的各个状态,这个知道的可能觉得很简单,但是不知道的可能想很久也想不到,我就是在看到这张图才真正理解为什么要采用二维数组表示这个状态(可能不同的人理解不同)。我们用f[i][j]表示字符串a的前i个与字符串b的前j个的最长公共子串,则状态转移方程是:

现在我们通过上面的那个图来理解一下这个方程,这个图显示的是求ABCBDAB与BDCABA的LCS,首先当某一个串为零,公共子串自然也为0了,然后如果某一个值上两个串相同那么自然是加一,最后不等的时候由图可以看到他们的来源有两个防线即上方和左方,通过这个我们就可以一步一步求出最大的公共子串了。

 /*
总结:这个是经典的LCS问题,主要是要找到递归方程
状态用二维数组表示(想到这个是难点)用f[a][b],表示字符串
A中前a个与字符串B中前b个的最大公共子串
递归方程:
f[i][j]= f[i-1][j-1]+1(相等的时候)
max(f[i][j-1],f[i-1][j])(不等的时候)
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
int main()
{
string a,b;
while(cin>>a>>b){
int dp[][]={};
int la=a.length();
int lb=b.length();
int maxx=;
for(int i=;i<la;i++){
for(int j=;j<lb;j++){
if(a[i]==b[j]){
dp[i+][j+]=dp[i][j]+;
if(maxx<dp[i+][j+])
maxx=dp[i+][j+];
}
else{
dp[i+][j+]=max(dp[i][j+],dp[i+][j]);
}
}
}
cout<<maxx<<endl;
}
return ;
}

  最后再稍微说一点最长公共子序列的用途,这个算法的一种用途就是用来判断两段文字的相似度,举一个我们最熟悉的例子,有两段程序,一段是原版,一段使用改变量名等手段做出来的那么他们的最长公共子序列一定会比较长,也就是说这个可以帮助我们找到看起来很不同的东西中的许多共同点。

二、最长递增子序列

  子序列这里就不用再介绍了,最长递增子序列也很好理解,就是给定一个序列 An a1 ,a2 ,  ... , an ,找出最长的子序列使得对所有 j ,ai aj 。。这个问题又是一个动态规划。它有两种解决方案:

  1、转化成LCS问题求解,初看这个貌似是没什么关系,但是我们至腰间这个序列排序之后与原来的求LCS得到的就是LIS了,个人觉得这个特别的    好,如果你自己能想出来那么你对LCS的理解也有一定深度了。

  2、继续动态规划,首先我们用f[i]表示以i结尾的LIS的长度,,这时我们就要考虑f[i]与前面那些值的关系,即这个值是要加载他前面那    个比他小的值上,这样才能达到最长。初始值自然是全部为1。

这里就不直接贴代码了,太简单了,给一个有一定改动的例子(其实没有本质性变化),合唱团:

题目描述:

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,
则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入:

输入的第一行是一个整数N(2 <= N <= 100),表示同学的总数。
第一行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。

输出:

可能包括多组测试数据,对于每组数据,
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

 /*
总结:这个是经典的LIS问题两种解决方法:
一、排序后转换成LCS
二、直接找转化方程,令L[i]表示以i结尾的最长递增子串长度,
则L[i]=max(l[j]+1,1)其中j表示前面小于i的且a[i]>a[j]的值
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
int main()
{
int n;
while(scanf("%d",&n)==&&n){
int a[];
int b[];
int c[];
int d[];
for(int i=;i<n;i++){
b[i]=;
c[i]=;
d[i]=;
scanf("%d",&a[i]);
for(int j=i-;j>=;j--){
if(a[i]>a[j]){
b[i]=max(b[i],b[j]+);
}
}
}
for(int i=n-;i>=;i--){
for(int j=i+;j<n;j++){
if(a[i]>a[j]){
c[i]=max(c[i],c[j]+);
}
}
}
int maxx=;
for(int i=;i<n;i++){
d[i]=b[i]+c[i];
//cout<<b[i]<<ends<<c[i]<<ends<<d[i]<<endl;
}
for(int i=;i<n;i++){
if(maxx<d[i]){
maxx=d[i];
}
}
printf("%d\n",n-maxx+);
}
return ;
}

最长公共子序列(LCS)和最长递增子序列(LIS)的求解的更多相关文章

  1. 最长公共子串(LCS:Longest Common Substring)

    最长公共子串(LCS:Longest Common Substring)是一个非常经典的面试题目,本人在乐视二面中被面试官问过,惨败在该题目中. 什么是最长公共子串 最长公共子串问题的基本表述为:给定 ...

  2. 每日一题-——最长公共子序列(LCS)与最长公共子串

    最长公共子序列(LCS) 思路: 代码: def LCS(string1,string2): len1 = len(string1) len2 = len(string2) res = [[0 for ...

  3. 最长连续公共子序列(LCS)与最长递增公共子序列(LIS)

    最长公共子序列(不连续) 实际问题中也有比较多的应用,比如,论文查重这种,就是很实际的一个使用方面. 这个应该是最常见的一种了,不再赘述,直接按照转移方程来进行: 按最普通的方式就是,直接构造二维矩阵 ...

  4. 最长公共子窜和最长公共子序列(LCS)

    他们都是用dp做;复杂度都是O(N方) 有一个大佬的博客写的很详细,是关于最长公共子序列的:https://blog.csdn.net/hrn1216/article/details/51534607 ...

  5. 最长回文子序列LCS,最长递增子序列LIS及相互联系

    最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...

  6. 最长公共子串LCS(Longest Common Substring)

    一.问题描述 寻求两个字符串中的最大公共字串,其中子串是指字符串中连续的字符组成的,而不是像子序列,按照字符的前后顺序组成.如str1="sgabacbadfgbacst",str ...

  7. [算法练习]最长公共子串(LCS)

    题目说明: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.比如"bab"和"caba"的最长公共子串是"ba"和" ...

  8. 最长公共子串(LCS) lg SP1811

    后缀自动机的一大用处就是求最长公共子串了 这道题的话题意就是给你两个字符串,求最长公共子串 做法的话是先使用一个字符串建立SAM,然后让另一个串在上面进行匹配 匹配的策略是优先匹配当前节点的下一个字符 ...

  9. 求两个字符串的最长公共子串(LCS)

    http://tianyunpu2008.blog.163.com/blog/static/6559379920089162236915/

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

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

随机推荐

  1. linux下的shell运算(加、减、乘、除)

    linux下的shell运算(加.减.乘.除) 标签: linuxshell运算加减乘除 2014-03-12 16:25 15127人阅读 评论(0) 收藏 举报 分类: linux(17) ((i ...

  2. oracle用户创建及权限设置及表空间

    建立表空间: create tablespace portx_data datafile 'D:\oracle_data\portx.dbf' size 50m autoextend on next ...

  3. PHP中文字符串编码转换

    2016年2月26日 16:47:13 星期五 情景: PHP从csv导入数据时乱码 $name = mb_convert_encoding($name, 'UTF-8', 'ASCII,GBK,GB ...

  4. 初识 MySQL 5.6 新功能、参数

    摘要: 继上一篇的文章 初识 MySQL 5.5 新功能.参数 之后,现在MySQL5.6 针对 MySQL5.5 各个方面又提升了很多,特别在性能和一些新参数上面,现在看看大致提升了哪些方面(后续不 ...

  5. ASM:《X86汇编语言-从实模式到保护模式》第12章:存储器的保护

    12章其实是11章的拓展,代码基本不变,就是在保护模式下展开讨论. ★PART1:存储器的保护机制 1. 修改段寄存器的保护 当执行把段选择子传到段寄存器的选择器部分的时候,处理器固件在完成传送之前, ...

  6. code vs1506传话(塔尖)+tarjan图文详解

    1506 传话  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题解   题目描述 Description 一个朋友网络,如果a认识b,那么如果a第一次收到 ...

  7. 从API请求数据的方法(主要适用于tp5)

    // 从api获取数据,$data是一个数组,默认为空,请求数据的方法可以通用,但是其它说明只适用于tp5 function postData($url,$data=''){ $ch = curl_i ...

  8. 【python】入门学习(十)

    #入门学习系列的内容均是在学习<Python编程入门(第3版)>时的学习笔记 统计一个文本文档的信息,并输出出现频率最高的10个单词 #text.py #保留的字符 keep = {'a' ...

  9. Android随笔:属性

    android:padding表示给控件的周围加上补白,这样不至于让文本内容会紧靠在边缘上. android:singleLine 设置为true 表示让这个TextView 只能单行显示. andr ...

  10. [Android Pro] Fragment中使用SurfaceView切换时闪一下黑屏的解决办法

    方法一.在Activity的onCreate中添加如下代码 getWindow().setFormat(PixelFormat.TRANSLUCENT); reference to :  http:/ ...