先来个板子

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+, M = 1e6+, mod = 1e9+, inf = 1e9+;
typedef long long ll; struct node
{
int c;
int num;
} u[N]; int i,j,k = ,n,m,x,y = ,T = ,ans = ,big = ,cas = ,num = ,len = ;
bool flag = ; bool cmp(node a,node b)
{
if (a.c==b.c) return a.num>b.num;
return a.c<b.c;
} vector <int> p;
int a[N],b[N],c[N];
int lena,lenb,dp[N]; int main()
{
scanf("%d%d",&lena,&lenb);
for(int i=;i<lena;i++) scanf("%d",&a[i]);
for(int i=;i<lenb;i++) scanf("%d",&b[i]);
for (i=;i<lenb;i++)
{
u[i].c=b[i];
u[i].num=i;
}
sort(u,u+lenb,cmp);//对b串排序
for (i=;i<lenb;i++)//排序后存入字符串c中,便于使用lower_bound
{
c[i]=u[i].c;
}
c[lenb]=1e9+;
for (i=;i<lena;i++)//计算A中每个元素在B中的序号
{
k=lower_bound(c,c+lenb,a[i])-c;
while (k<lenb && a[i]==c[k])
{
p.push_back(u[k].num);
k++;
}
}
if(p.size()==) {
printf("1\n");
return ;
}
n=p.size();
dp[] = p[] ; dp[] = -inf ;
for( i = ans = ; i < n ; i++)
{
int l = , r = ans ;
while( l <= r )
{
int mid = ( l + r ) >> ;
if( dp[mid] >= p[i] ) r = mid - ;
else l = mid + ;
}
if( r == ans ) ans++,dp[r+] = p[i] ;
else if( dp[r+] > p[i] ) dp[r+] = p[i] ;
}
printf("%d\n",ans+);
return ;
}

最长公共子序列问题:

给定2个字符串,求其最长公共子串。如abcde和dbada的最长公共字串为bd。

动态规划:dp[i][j]表示A串前i个和B串前j个的最长公共子串的长度。

若A[i] == B[j] , dp[i][j] = dp[i-1][j-1] + 1;

否则 dp[i][j] = max(dp[i-1][j],dp[i][j-1]);

时间复杂度O(N*M)。

dp[i][j]仅在A[i]==B[j]处才增加,对于不相等的地方对最终值是没有影响的。

故枚举相等点处可以对其进行优化。

则对于dp[i][j](这里只计算A[i]==B[j]的i和j),取最大的dp[p][q],满足(p<i,q<j),通过二叉搜索树可以再logn的时间里获取到最大的dp[p][q],区间在[0,j)。

这里也可将其转化为最长递增子序列问题。

举例说明:

A:abdba

B:dbaaba

则1:先顺序扫描A串,取其在B串的所有位置:

2:a(2,3,5) b(1,4) d(0)。

3:用每个字母的反序列替换,则最终的最长严格递增子序列的长度即为解。

替换结果:532 41 0 41 532

最大长度为3.

简单说明:上面的序列和最长公共子串是等价的。

对于一个满足最长严格递增子序列的序列,该序列必对应一个匹配的子串。

反序是为了在递增子串中,每个字母对应的序列最多只有一个被选出。

反证法可知不存在更大的公共子串,因为如果存在,则求得的最长递增子序列不是最长的,矛盾。

最长递增子序列可在O(NLogN)的时间内算出。

dp[i] = max(dp[j]+1) ( 满足 a[i] > a[j] && i > j )

显然对于同样的如dp[k] = 3,假定k有多个,记为看k1,k2,.....,km 设k1 < k2 < .... < km

在计算dp[i]的时候,k2,k3,....,km显然对结果没有帮助,取当前最小的k,

满足ans[k] = p (最小的p使得dp[p]=k) ,每次二分,更新ans[dp[i]] = min(ans[dp[i]],i).

ps:LCS在最终的时间复杂度上不是严格的O(nlogn),不知均摊上是不是。

举个退化的例子:

如A:aaa

B:aaaa

则序列321032103210

长度变成了n*m ,最终时间复杂度O(n*m*(lognm)) > O(n*m)。

这种情况不知有没有很好的解决办法。

最长公共子序列 nlogn的更多相关文章

  1. 【算法】最长公共子序列(nlogn)

    转载注明出处:http://blog.csdn.net/wdq347/article/details/9001005 (修正了一些错误,并自己重写了代码) 最长公共子序列(LCS)最常见的算法是时间复 ...

  2. P3402 最长公共子序列(nlogn)

    P3402 最长公共子序列 题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子 ...

  3. 洛谷1439:最长公共子序列(nlogn做法)

    洛谷1439:最长公共子序列(nlogn做法) 题目描述: 给定两个序列求最长公共子序列. 这两个序列一定是\(1\)~\(n\)的全排列. 数据范围: \(1\leq n\leq 10^5\) 思路 ...

  4. LCS最长公共子序列(最优线性时间O(n))

    这篇日志主要为了记录这几天的学习成果. 最长公共子序列根据要不要求子序列连续分两种情况. 只考虑两个串的情况,假设两个串长度均为n. 一,子序列不要求连续. (1)动态规划(O(n*n)) (转自:h ...

  5. 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列

    出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...

  6. 动态规划 最长公共子序列 LCS,最长单独递增子序列,最长公共子串

    LCS:给出两个序列S1和S2,求出的这两个序列的最大公共部分S3就是就是S1和S2的最长公共子序列了.公共部分 必须是以相同的顺序出现,但是不必要是连续的. 选出最长公共子序列.对于长度为n的序列, ...

  7. Longest Common Substring(最长公共子序列)

    Longest Common Substring Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...

  8. 洛谷P1439 【模板】最长公共子序列

    题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子 ...

  9. LIS LCS 最长上升子序列 最长公共子序列 ...

    最长上升子序列,问题定义:http://blog.csdn.net/chenwenshi/article/details/6027086 代码: public static void getData( ...

随机推荐

  1. POJ 2230 DFS

    题意: Bessie 最近做了农场看守,他每天晚上的工作就是巡视农场并且保证没有坏人破坏农场.从谷仓出发去巡视,并且最终回到谷仓. Bessie 视力不是很好,不能像其他农场的看守一样,对农场的每一条 ...

  2. Dijkstra TYVJ 1031热浪 Dijkstra测试数据

    测试用邻接表写得Dijkstra 代码写得很烂. 描述 德克萨斯纯朴的民眾们这个夏天正在遭受巨大的热浪!!!他们的德克萨斯长角牛吃起来不错,可是他们并不是很擅长生產富含奶油的乳製品.Farmer Jo ...

  3. 连接Oracle数据库帮助类

    连接Oracle数据库帮助类,就是把连接Oracle数据库的方法封装起来,只需要在其它页面调用就可,不需要重复写. import java.sql.Connection; import java.sq ...

  4. java程序员级别划分

    IT路虽好,却难走.1级   为会基本语法 大学里的JAVA教程 能及格 2级   自己可以写个 俄罗斯方块,扫雷,贪吃蛇, 拼图之类的小游戏 3级   能够进手机游戏CP,SP公司,做手机游戏 或者 ...

  5. <aop:aspectj-autoproxy />

    通过配置织入@Aspectj切面 虽然可以通过编程的方式织入切面,但是一般情况下,我们还是使用spring的配置自动完成创建代理织入切面的工作. 通过aop命名空间的<aop:aspectj-a ...

  6. Mac下php连接mysql数据库失败解决办法

    通过phpmyadmin连接mysql成功,但是通过php连接数据库失败,执行如下php语句 ? 1 @mysql_connect("localhost","root&q ...

  7. CorelDRAW2019新耀发布会,报名即可领红包!

    ​30年时光荏苒!眨眼风惊雨过. 在1989年的春天,CorelDRAW 1.0正式发布,一经面世就掀起了图形设计行业革命浪潮,这个图形工具不仅给设计师提供了矢量图像.页面设计,更能应用于网站制作.位 ...

  8. SP1825 FTOUR2 - Free tour II 点分治+启发式合并+未调完

    题意翻译 给定一棵n个点的树,树上有m个黑点,求出一条路径,使得这条路径经过的黑点数小于等于k,且路径长度最大 Code: #include <bits/stdc++.h> using n ...

  9. Uoj #274. 【清华集训2016】温暖会指引我们前行 LCT维护边权_动态最小生成树

    Code: 行#include<bits/stdc++.h> #define ll long long #define maxn 1000000 #define inf 100000000 ...

  10. CF1168B Good Triple 性质分析_好题

    题意翻译 给出01串s,求数对[l,r]个数,使得能找到至少一对[x,k],使1<=x,k<=|s|且l<=x<x+2k<=r且s[x]=s[x+k]=s[x+2k] 题 ...