Luogu P1439

令f[i][j]表示a的前i个元素与b的前j个元素的最长公共子序列

可以得到状态转移方程:

if (a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1;
dp[i][j]=max(dp[i][j],dp[i-1][j],dp[i][j-1]);

时空复杂度都为O(n2)

对于本题这种做法显然是无法接受的。

我们可以对这个题目进行转化。仔细看题,可以发现a,b两个序列都是1-n的排列。

那么,我们可以利用映射,将a中的数一一映射成为1,2,3,4,5……,n

再把b中的数一一对应更改。由于a中的数是升序的,所以b中的最长上升子序列的长度就是a与b的最长公共子序列。LCS问题就转化成了LIS问题。

例如样例

a的 3 2 1 4 5映射为1 2 3 4 5

则b从1 2 3 4 5变为3 2 1 4 5

结合上面的分析就会变得很容易理解了。

#include<algorithm>
#include<cstdio>
using namespace std;
int n,a[100005],b[100005],k[100005],dp[100005],ans;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
k[a[i]]=i;
}
for (int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
b[i]=k[b[i]];
}
dp[1]=1;
for (int i=2;i<=n;i++)
{
for (int j=1;j<i;j++)
{
if (b[i]>b[j]) dp[i]=max(dp[i],dp[j]+1);
else dp[i]=max(1,dp[i]);
}
}
for (int i=1;i<=n;i++)
ans=max(ans,dp[i]);
printf("%d",ans);
return 0;
}

这个动态规划可以很轻松地写出来,但是我们发现时间还是不够优秀。

那么我们就要对这个算法进行优化。对于LIS问题,有一种广为人知的O(nlogn)的解法。

dp[i]中存储长度为i的LIS的最后一个数。

如果符合单调上升就直接增长长度并记录,否则就利用STL二分查找出dp数组中第一个大于b[i]的位置,替换它。

举个例子,例如 3 6 2 4 7 8

一开始的序列{3},接着变成{3,6}

遇到2之后我们将3替换{2,6},为什么可以进行替换呢?

因为后面还有一个4可以替换掉6,构成一条更优的序列。(保证结尾尽可能小,就能保证序列尽可能优)

如果后面没有4呢?那么也没有关系,因为这个2即使修改了也对答案没有任何影响。

(想一想为什么)

dp[1]=b[1];
len=1;
for (int i=2;i<=n;i++)
{
if (b[i]>dp[len]) dp[++len]=b[i];//记录并增长长度。
else
{
int x=upper_bound(dp+1,dp+1+len,b[i])-dp;
dp[x]=b[i];
//利用STL二分查找出dp数组中第一个大于b[i]的位置,替换它。
} }

完整代码如下:

#include<algorithm>
#include<cstdio>
using namespace std;
int n,a[100005],b[100005],k[100005],dp[100005],ans,len;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
k[a[i]]=i;//映射
}
for (int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
b[i]=k[b[i]];//对应修改
}
dp[1]=b[1];
len=1;
for (int i=2;i<=n;i++)
{
if (b[i]>dp[len]) dp[++len]=b[i];
else
{
int x=upper_bound(dp+1,dp+1+len,b[i])-dp;
dp[x]=b[i];
}
}
printf("%d",len);
return 0;
}

【Luogu P1439】最长公共子序列(LCS)的更多相关文章

  1. Luogu 3402 最长公共子序列(二分,最长递增子序列)

    Luogu 3402 最长公共子序列(二分,最长递增子序列) Description 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: ...

  2. 1006 最长公共子序列Lcs

    1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdks ...

  3. 动态规划之最长公共子序列LCS(Longest Common Subsequence)

    一.问题描述 由于最长公共子序列LCS是一个比较经典的问题,主要是采用动态规划(DP)算法去实现,理论方面的讲述也非常详尽,本文重点是程序的实现部分,所以理论方面的解释主要看这篇博客:http://b ...

  4. 编程算法 - 最长公共子序列(LCS) 代码(C)

    最长公共子序列(LCS) 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 给定两个字符串s,t, 求出这两个字符串最长的公共子序列的长度. 字符 ...

  5. C++版 - Lintcode 77-Longest Common Subsequence最长公共子序列(LCS) - 题解

    版权声明:本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C++版 - L ...

  6. POJ 1458 Common Subsequence(最长公共子序列LCS)

    POJ1458 Common Subsequence(最长公共子序列LCS) http://poj.org/problem?id=1458 题意: 给你两个字符串, 要你求出两个字符串的最长公共子序列 ...

  7. 51Nod 1006:最长公共子序列Lcs(打印LCS)

    1006 最长公共子序列Lcs  基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). ...

  8. 51nod 1006 最长公共子序列Lcs 【LCS/打印path】

    1006 最长公共子序列Lcs  基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). ...

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

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

  10. 51nod 1006:最长公共子序列Lcs

    1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). ...

随机推荐

  1. JVM学习记录3--垃圾收集器

    贴个图 Serial收集器 最简单的收集器,单线程,收集器会暂停用户线程,称为"stop the world". ParNew收集器 Serial收集器的多线程版本,其它类似.默认 ...

  2. JVM学习记录2--垃圾回收算法

    首先要明确,垃圾回收管理jvm的堆内存,方法区是堆内存的一部分,所以也是. 而本地方法栈,虚拟机栈,程序计数器随着线程开始而产生,线程的结束而消亡,是不需要垃圾回收的. 1. 判断对象是否可以被回收 ...

  3. p6spy打印SQL

    一 Springboot项目 <dependency> <groupId>p6spy</groupId> <artifactId>p6spy</a ...

  4. 实战SpringCloud响应式微服务系列教程(第九章)使用Spring WebFlux构建响应式RESTful服务

    本文为实战SpringCloud响应式微服务系列教程第九章,讲解使用Spring WebFlux构建响应式RESTful服务.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 从本节开始我们 ...

  5. java迭代器 常用

    19 //使用迭代器遍历ArrayList集合 20 Iterator<String> listIt = list.iterator(); 21 while(listIt.hasNext( ...

  6. 配置Docker镜像加速

    1.在docker toolbox执行下面的命令进入VM bash docker-machine ssh default 2.执行下面的命令修改profile文件: sudo vi /var/lib/ ...

  7. Security整合spring boot

    Security整合spring boot 1.基础概念 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spri ...

  8. 防抖(debounce)和 节流(throttling)

    防抖(debounce)和 节流(throttling) 1.防抖和节流出现的原因 防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案. 在给DOM绑定事件时,有些事件我们是无法控制触发频率的. ...

  9. C++学习笔记7_多态

    1. 类与类之间的关系class A{ public: int a; void funcA() {}}包含: class B { public: void funcB(){} A a; }//如果类B ...

  10. OV5640摄像头的数据处理配置流程(一)

    module RGB_init( //系统信号输入(时钟+复位) input cmos_clk_i, //模块控制时钟 input rst_n_i, //系统复位信号 //OV5640输出信号(从56 ...