这个算法其实是因为LIS有NlogN的作法,把LCS转化为了LIS来做。

对于序列A{},B{},我们可以记录下来B中的每个元素在A中出现的位置,按顺序保存在一个新序列当中,

如果有多个位置按倒序写,没有就不用写,然后对这个新序列求一个LIS就是两个序列的LCS长度。

为什么这样可行呢,我们可以这样考虑,对于A序列,下标编号记为1---n1,B和A的最长公共子序列在A中对应的编号肯定是递增的,

所以B中的这些元素对应的A的编号也是递增的,为了重复计算当有多个编号时倒序存入,表示只能选一个,尽管有多个编号但在B中这只是一个元素。

A={3,9,7,10,3}   B={5,3,7,3}

列出B对应的A中的编号(1--5)

5:无

3:1,5

7:3

3:1,5

如果按照15315来计算的话相当于B中的一个3当做了两个,但其实并不是,所以应是51351,LIS是1,3,5,也就是A中的3,7,3

https://vjudge.net/problem/UVA-10635

很脑洞的一道题,看似再考LCS实则要用LIS写才能不超时。

题意,给出两个序列A,B,长度分别是p+1和q+1,且A[1]=B[1]=1,A中的元素各不相同B也一样,长度不超过250^2,求AB的LCS。

用求LCS的方法算复杂度O(pq)肯定超时,由于元素都不相同,我们将A中的元素编号为1~p+1,在B中将A中出现过的元素改为对应的编号,没出现的编号为0(也可以删除)

然后的任务就是在B中找一个LIS,利用二分查找减小复杂度。

这其实就是一种LCS的O(NlogN)的作法。

 #include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
map<int,int>M;
int main()
{ int n,m,p,q,i,k,j,t;
int a[],b[],g[];
//freopen("in.txt","r",stdin);
cin>>t;
for(int test=;test<=t;++test)
{
M.clear();
int x=;
cin>>n>>p>>q;
for(i=;i<=p+;++i)
{
scanf("%d",a+i);
if(!M[a[i]]) M[a[i]]=x++;
}
for(i=;i<=q+;++i)
{
scanf("%d",b+i);
b[i]=M[b[i]];
}
memset(g,inf,sizeof(g));
for(i=;i<=q+;++i)
{
*lower_bound(g,g+,b[i])=b[i];
}
printf("Case %d: %d\n",test,(int)(lower_bound(g,g+,inf)-g));
}
return ;
}

再来看一道,

http://www.ifrog.cc/acm/problem/1097

回忆起B在A中只有一个对应的点时,当时一直按得LIS来做但仔细想一想要求的不就是A和B的LCS吗,原来我早就写过nlogn的LCS做法竟然没有意识到。

这个问题相当于B中每个元素对应A中的多个元素,所以将匹配的A的编号记录下来做一次LIS就是答案,处理时依然要倒序插入。

倒序的好处在于如果选那么肯定只出现一个要么就不出现,不会产生一个B对应了多个A。

 #include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
map<int,int>M;
int x[];
int g[];
int main()
{ int n,m,p,q,i,k,j,t;
while(cin>>n){int a[];p=;
for(i=;i<=n;++i)
{
for(j=;j<=;++j)
{
scanf("%d",a+j);
}sort(a+,a++,greater<int>());
for(int di=;di<=;++di)
{
if(a[di]==a[di-]) continue;
x[p++]=a[di];
}
}
memset(g,inf,sizeof(g));
for(i=;i<p;++i)
*lower_bound(g,g+p+,x[i])=x[i];
cout<<(lower_bound(g,g+p+,inf)-g)<<endl;
}
return ;
}

LCS 的 NlogN作法的更多相关文章

  1. LIS与LCS的nlogn解法

    LIS(nlogn) #include<iostream> #include<cstdio> using namespace std; ; int a[maxn]; int n ...

  2. O(nlogn)实现LCS与LIS

    序: LIS与LCS分别是求一个序列的最长不下降序列序列与两个序列的最长公共子序列. 朴素法都可以以O(n^2)实现. LCS借助LIS实现O(nlogn)的复杂度,而LIS则是通过二分搜索将复杂度从 ...

  3. uva 10635 LCS转LIS

    这道题两个数组都没有重复的数字,用lcs的nlogn再适合不过了 #include <iostream> #include <string> #include <cstr ...

  4. 【CZY选讲·扩展LCS】

    题目描述 给出两个仅有小写字母组成的字符串str1 和str2,试求出两个串的最长公共子序列. 数据范围 |str1| ⩽ 1000; |str2| ⩽ 10^6 题解:    ①直接进行LCS( ...

  5. NYIST 760 See LCS again

    See LCS again时间限制:1000 ms | 内存限制:65535 KB难度:3 描述There are A, B two sequences, the number of elements ...

  6. OI总结

    当下考的钟声叮当响起,该走了,一年半的OI竞赛就此结束 留下了很多遗憾.也拥有过一段美好的竞赛生活 结识了一群优秀的OI战友,一起进步一起开心一起忧愁,但这一切的一切都将在今晚变成过去式,CSp的好与 ...

  7. dp--最长上升子序列LIS

    1759:最长上升子序列 总时间限制:  2000ms 内存限制:  65536kB 描述 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对 ...

  8. 动态规划 Dynamic Programming 学习笔记

    文章以 CC-BY-SA 方式共享,此说明高于本站内其他说明. 本文尚未完工,但内容足够丰富,故提前发布. 内容包含大量 \(\LaTeX\) 公式,渲染可能需要一些时间,请耐心等待渲染(约 5s). ...

  9. O(nlogn)LIS及LCS算法

    morestep学长出题,考验我们,第二题裸题但是数据范围令人无奈,考试失利之后,刻意去学习了下优化的算法 一.O(nlogn)的LIS(最长上升子序列) 设当前已经求出的最长上升子序列长度为len. ...

随机推荐

  1. 洛谷 P4145 上帝造题的七分钟2 / 花神游历各国

    洛谷 这题就是区间开根号,区间求和.我们可以分块做. 我们记布尔数组vis[i]表示第i块中元素是否全部为1. 因为显然当一个块中元素全部为1时,并不需要对它进行根号操作. 我们每个块暴力开根号,因为 ...

  2. python函数回顾:slice()

    描述 slice() 函数实现切片对象,主要用在切片操作函数里的参数传递. 语法 class slice(stop) class slice(start, stop[, step]) 参数说明: st ...

  3. python中如何去掉unicode编码前面的u?

    1.列表类型(用join方法) myUlist = [u'AB', u'AB', u'AB', u'AB'] print myUlist print ", ".join(myUli ...

  4. MySQL数据库(3)- 完整性约束、外键的变种、单表查询

    一.完整性约束 在创建表时候,约束条件和数据类型的宽度都是可选参数. 作用:用于保证数据的完整性和一致性. 1.not null(不可空)与default 示例一:插入一个空值,如下: mysql&g ...

  5. Drawable.Callback

     一.介绍 public abstract void invalidateDrawable (Drawable who) Called when the drawable needs to be re ...

  6. webpack基础使用

    环境: win10, webpack v3.5.6, node v8.4, npm v5.3. 安装与配置 新建一个项目目录demo, 在当前目录执行如下命令: npm init -y npm ins ...

  7. ptyhon从入门到放弃之操作系统基础

    *2.操作系统操作系统基础1.什么是操作系统操作系统就是一个协调.管理和控制计算机硬件和软件的控制程序.2.为何要有操作系统现代的计算机系统主要是由一个或者多个处理器,主存,硬盘,键盘,鼠标,显示器, ...

  8. IO阻塞模型 非阻塞模型

       IO阻塞模型(blocking IO) 在linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概是这样:  所以,blocking IO的特点就是在IO执行的两 ...

  9. Ecstore 会员中心 菜单添加一项

    1.会员中心 添加菜单 ecstore_合并支付总结_会员中心添加菜单_20160113 class : b2c_ctl_site_member (图 1)     第一步: (图1)         ...

  10. Python:笔记(4)——高级特性

    Python:笔记(4)——高级特性 切片 取一个list或tuple的部分元素是非常常见的操作.Python提供了切片操作符,来完成部分元素的选取 除了上例简单的下标范围取元素外,Python还支持 ...