logn的最长公共子序列

最长公共子序列nlogn算法 求两个序列的最大公共子序列(LCS),普遍的动态规划算法时间复杂度为O(n^2),在两个序列的长度很长的时候运行时间过长。可以转化为最长上升子序列(LIS)来求,时间复杂度可以优化到nlogn。1.首先说一下转化为LIS的方法:  找到s1序列中每个元素在s2序列中的位置,并用这些在s2中的位置替换s1中对应的元素,注意s1中的元素在s2中当有多个位置(a1,a2,a3……)时,要降序排列(a1>a 阅读详情

最长公共子序列(LCS)最常见的算法是时间复杂度为O(n^2)的动态规划(DP)算法,但在James W. Hunt和Thomas G. Szymansky 的论文”A Fast Algorithm for Computing Longest Common Subsequence”中,给出了O(nlogn)下限的一种算法。
定理:设序列A长度为n,{A(i)},序列B长度为m,{B(i)},考虑A中所有元素在B中的序号,即A某元素在B的序号为{Pk1,Pk2,..},将这些序号按照降序排列,然后按照A中的顺序得到一个新序列,此新序列的最长严格递增子序列即对应为A、B的最长公共子序列。
举例来说,A={a,b,c,d,b},B={b,c,a,b},则a对应在B的序号为2,b对应序号为{3,0},c对应序号为1,d对应为空集,生成的新序列为{2,3, 0, 1, 3, 0},其最长严格递增子序列为{0,1,3},对应的公共子序列为{b, c, b}

实现代码:(洛谷P1439):

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<string>
using namespace std;
const int N=1000005;
vector<int>v[N],a,d;
int main()
{
    int n,i,j,A[N],B[N];
    cin>>n;
    for(i=1;i<=n;i++)scanf("%d",&A[i]);
    for(i=1;i<=n;i++)scanf("%d",&B[i]);
    for(i=n;i;i--)
        v[B[i]].push_back(i);//保证后面a中的序列是按照B中从前往后的顺序出现,所以要倒序
    for(i=1;i<=n;i++){
        int now=A[i];
        if(v[now].empty())continue;
        for(int j=0;j<v[now].size();j++)//将A中的数按在B中出现的顺序加入a
            a.push_back(v[now][j]);
    }
    if(!a.empty()){//logn的最长上升子序列
        d.push_back(a[0]);
        for(i=1;i<a.size();i++){
            if(a[i]>d.back())d.push_back(a[i]);
            else{
                vector<int>::iterator iter=lower_bound(d.begin(),d.end(),a[i]);
                *iter=a[i];
            }
        }
    }
    cout<<d.size()<<endl;

    return 0;
}

字符串版:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cstring>
using namespace std;
vector<int>v[30],a,d;
int main()
{
    freopen("test.in","r",stdin);
    freopen("zj.out","w",stdout);
    int n;string str1,str2;
    cin>>n;getchar();getline(cin,str1);getline(cin,str2);
    for(int i=str2.size()-1;i>=0;i--)v[str2[i]-'a'].push_back(i);
    for(int i=0;i<n;i++){
        int now=str1[i]-'a';
        if(v[now].empty())continue;
        for(int j=0;j<v[now].size();j++)
            a.push_back(v[now][j]);
    }
    if(!a.empty()){
        d.push_back(a[0]);
        for(int i=0;i<a.size();i++){
            if(a[i]>d.back())d.push_back(a[i]);
            else{
                vector<int>::iterator iter=lower_bound(d.begin(),d.end(),a[i]);
                *iter=a[i];
            }
        }
    }
    cout<<d.size()<<endl;

    return 0;
}

附:朴素o(n2)的最长公共子序列:

#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<cstring>
using namespace std;
int f[200005][200005];
int main()
{
    freopen("test.in","r",stdin);
    freopen("bl.out","w",stdout);
    int n,i,j,k;
    string str1,str2;
    cin>>n;getchar();getline(cin,str1);getline(cin,str2);
    //if(str1[0]==str2[0])f[0][0]=1;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            if(str1[i]==str2[j])f[i][j]=max(f[i][j],((i==0||j==0)?0:f[i-1][j-1])+1);
            else{
                f[i][j]=max(f[i][j],max(i==0?0:f[i-1][j],j==0?0:f[i][j-1]));
            }
        }
    }
    cout<<f[n-1][n-1]<<endl;

    return 0;
}
面试题 | 求两个字符串的最长公共子串 要求时间复杂度O(nm),空间复杂度O(1) 来源:牛客网-编程题 题意:给定两个字符串str1和str2,输出两个字符串的最长公共子串,如果最长公共子串为空,输出-1。 思路: 用动态规划空间复杂度会是 O(nm)O(nm)O(nm),我们发现计算每一个 f[i][j]f[i][j]f[i][j] 的时候只需要计算f[i−1][j−1]f[i-1][j-1]f[i−1][j−1],所以只要按照斜线方向(遍历 n + m - 1条斜线)计算所有的值,用一个变量维护最大值,那么空间复杂度就可以降低到 O(1)O(1)O(1) 核心:知道如何遍历 n + 阅读详情

相关推荐

中国IP发展之面面观

谢学军/邱善勤2006-1-25 9:29:28电子经理世界       IP远没有我们当初想象的那么简单   当SoC设计方法学刚刚传到国内的时候,学界为之欢呼雀跃,由于IP/SoC设计技术的使用,可以将发达国家用几年甚至十几年积累起来的设计技术直接为我所用,使中国的集成电路跳过漫长的积累阶段,迅速站到较高的起点上。因此在当时看来,IP/SoC设计技术是我国提升设计水平、发展

klxdmm305的专栏 1188

数据结构与算法之最长公共子串

最长公共子串问题是指给定两个字符串S1和S2,求它们的公共子串中最长的那一个。其实就是求两个字符串的最长重复子串。最朴素的算法就是枚举S1和S2的每一对子串,然后判断它们是否相等,时间复杂度是O(n^3)。但是这种算法效率太低,无法满足实际需求。一般采用动态规划的思想进行求解,令dp[i][j]表示以S1的前i个字符和S2的前j个字符为结尾的公共子串的长度,当S1[i]=S2[j]时,dp[i][j]=dp[i-1][j-1]+1;否则dp[i][j]=0。最后找出dp[i][j]的最大值即可。

weixin_47225948的博客 4925

Linux USB设备命名规则

有一个USB设备,接到了Linux系统的终端的某个插口上,那么怎么找到这个设备对应设备路径呢?这个USB设备虚拟了多个功能(三个串口和一个网卡), 如何找到对应操作路径呢?

weixin_43132521的博客 1698

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

本章讲解: 1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度; 2. 与之类似但不同的最长公共子串方法。 最长公共子串用动态规划可实现O(n^2)的时间复杂度,O(n^2)的空间复杂度;还可以进一步优化,用后缀数组的方法优化成线性时间O(nlogn);空间也可以用其他方法优化成线性。 3.LIS(最长递增序列)DP方法可实现O(n^2)的时间复杂度,进一步优化最佳可达到O(nlogn) 一些定义: 字符串 X, Y 长度 分别m,n 子串:字符串S的子串r[i,...,j.

zhaoxiaoba的博客 1268

使用DevExpress22.X(Patch)控件库在VisualStudio2022使用C#进行Winform、WPF应用的开发,看这一篇就够了!

写在开头,Dev Express是个十分强大的控件库(下文简称Dev),但碍于其高昂的使用费用,“出于学习目的”,我们一般使用的都是Patch版本(在版权意识日趋加强的当下,不要提那两个字,现在加上那些字,百度都搜不出内容)。

平凡之路 2万+

STLink驱动安装全攻略:从卸载到Keil配置的完整避坑指南

本文提供了STLink驱动安装与Keil环境配置的完整避坑指南。详细讲解了从驱动卸载、重装到Keil调试器设置的每一步,并针对常见的设备无法识别、连接不稳定等问题给出了深度解决方案,帮助开发者快速搭建稳定的STM32开发环境。

weixin_29182481的博客 424

lcs 最长公共子序列 O(nlogn)算法

最长公共子序列问题: 给定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]); 时间复杂...

weixin_34161029的博客 684

盘点军工行业软件研发的那些常用GJB标准

GJB5000、2786、438、141、102、8114等...

文章主要涉及嵌入式软件开发、测试、项目管理等,欢迎交流,共同进步。 9444

Prince and Princess (最长公共子序列n*logn)

Prince and PrincessInput: Standard InputOutput: Standard OutputTime Limit: 3 SecondsIn an n x n chessboard, Prince and Princess plays a game. The squares in the chessboard are numbered 1, 2, 3 ... n*n...

a1046765624的博客 1616

STM32F103C8T6心电采集实战:从PCB设计到上位机开发的完整指南(附TI杯开源资料)

本文详细介绍了基于STM32F103C8T6的心电采集系统开发全流程,从PCB设计到上位机开发,特别适合大学生电子设计大赛参赛者参考。内容涵盖硬件设计精要、软件算法优化及上位机开发技巧,并附TI杯开源资料,帮助开发者低成本实现医疗级心电信号采集。

kafka6courier的博客 194

一文吃透 OData Deep Insert:从框架原理到 ABAP 实战

本文面向ABAP工程师,解析OData服务中的Deep Insert技术。文章首先阐述Deep Insert的业务背景,说明其适用于父子层级数据必须成组创建的场景(如销售订单与行项目)。随后深入框架实现机制,介绍SAP Gateway如何通过CREATE_DEEP_ENTITY方法处理嵌套请求,并强调开发者的责任边界。通过销售订单案例,文章对比了Deep Insert与$batch的适用场景差异,提供请求负载示例和DPC_EXT实现骨架代码。最后给出MPC_EXT声明深结构的三种套路,以及事务处理和错误处理

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 225

最长公共子序列 LCS n*logn算法

LCS 最长公共子序列 //n*logn

m0_74039681的博客 316

【Camera2教程一】Camera2的框架Pipeline和framework中核心类和接口的详细介绍

Camera2 的 API 模型被设计成一个 Pipeline(管道),它按顺序处理每一帧的请求并返回请求结果给客户端。

jiangchaobing_2017的博客 792

Prince and Princess UVA - 10635 (n*logn 的最长公共子序列)

思路:求两个串的最长公共子序列,将其转化成求最长上升子序列。 转化方法:将第一个串按顺序编号,将第二个串HASH,然后求hash后的串的最长上升子序列。 代码: #include &lt;bits/stdc++.h&gt; using namespace std; const int maxn=1e5+7; const int inf=0x3f3f3f3f; typedef long lo...

untilyouydc 203

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

算法:最长公共子序列(做法小计)

给出长度为n的数组a,长度为m的数组b,求解其最长公共子序列

m0_73755253的博客 832

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

LCS 最长公共子序列

前言 LCS(longest common string)最长公共子序列 我学习的时候经历了从一般的O(n2)复杂度,数组开maxn* maxn; 用滚动数组优化空间; LCS转化成LIS,时间复杂度O(logn)。本次也按照这个顺序进行叙述。 一般的O(n2)算法 int dp[maxn][maxn]; mem(dp,0); for (int i = 0; i &l...

彤云望月 206

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

13.最长公共子序列

线性DP

weixin_60869516的博客 308

[DP_LIS] UVA10635

神奇的LCS和LIS的关系

Aria461863631的博客 411

LIS,LCS,一道LIS题

LCS,最长公共子序列,根据算导的推论,可以得到如下公式: c[ i ][ j ] = 0  (i = 0或j = 0) c[ i ][ j ] = c[ i-1 ] [ j-1 ] + 1 (i,j>0且xi = yj) c[ i ][ j ] = max (c [ i ][ j-1 ],c [ i-1 ][ j ])  (i , j>0且 xi≠yj ) 自己根据算导敲了下:(感觉时间

qq_33216593的博客 404

POJ 2533 Longest Ordered Subsequence (LIS DP)

最长公共自序列LIS 三种模板,但是邝斌写的好像这题过不了 N*N 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int N = 41000; 6 int a[1010],dp[1010...

weixin_30613343的博客 55

【模板】最长公共子序列 详细解析

中下标比当前元素小,因为不用差分,考虑使用树状数组维护比某下标小的 dp 最大值,此时查询满足条件的时间复杂度变为。观察朴素 dp,我们要求的便是在当前元素下标之前的最大 dp 值,即之前的元素在。解释:如果我们要从之前的序列转移过来,那么一定要满足当前元素的下标在。中都要分别在被转移的元素后面,时间复杂度为。首先考虑朴素的 dp,记。,总时间复杂度优化为。

jiangdongzhen的博客 311

Common Subsequence(DP求LCS)

题意:求两字符串最长公共子序列长度 先假设字符串起点为1,好讲些。dp[i][j]表示字符串1的前i字符和字符串2的前j个字符的最长公共子序列长度,下面我们来推到一下状态转移方程 if (arr1[i] == arr2[j]) dp[i][j] = dp[(i - 1)][(j - 1)] + 1; 为什么是由dp[i-1][j-1]转移,而不是dp[i-1][j]或dp[i][j-1]呢?因为如果arr[i]==arr[j]时,必定有dp[i][j]>da[i-1][j-1],但不一定有dp[i][

donnameの博客 207

UVA10635 Prince and Princess(LIS)

题意:王子和公主同时从1出发走到 n*n, 求他们两个路径的最长公共子序列; 思路:因为这题n有250,如果用LCS负责度为O(n^2),容易超时,于是我们选择它的优化版Lis算法来求最长公共子序列,这样我们的复杂度就降为O(n*logn)了。 Lis算法:      先回顾经典的O(n^2)的动态规划算法,设A[t]表示序列中的第t个数,F[t]表示从1到t这一段中以t结尾的最长上升子序列

Yedl的专栏 960

最长上升子序列+最长公共子序列

最长上升子序列参考——时间复杂度:动态规划O(n^2)、贪心+二分O(n*log n) 最长公共子序列参考——动态规划O(n*m)

weixin_43563311的博客 122

动态规划总结

经典问题: 一、最长上升子序列:      问题描述如下:  设L=是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=,其中k1 a[n] 则存在长度为1的不下降子序列a[n-1]或者a[n]。  有了以上的思想,DP方程就呼之欲出了(这里是顺序推的,不是逆序的): DP[I]=MAX(1,DP[J]+1)  J=0,1,...,I-1  但这样的想法实现起来是)O(n^2)

独行无疆的博客 304

【洛谷P1439】最长公共子序列

链接 (N方过百万是lsh的事,和我css有什么关系。) 两个序列的最长公共子序列,一定是这个样子的(此处样例,不唯一): 然后给映射一下,很容易发现,公共子序列的映射结果一定是上升的。 于是乎就把问题转化成了求最长上升子序列。 这里有一个log(n)的求法: f[len]表示长度为len的上升子序列的结尾。 在dp时,如果大于结尾,就把他加到末尾; 如果小于结尾,就在前面二分...

Sakura_Chiyo的博客 362
上一篇: (模板)卡时间
下一篇: 关于__int128
HumveeA6
博客等级 码龄17年 12粉丝 175原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值