博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷 [p1439] 最长公共子序列 (NlogN)
阅读量:4980 次
发布时间:2019-06-12

本文共 1638 字,大约阅读时间需要 5 分钟。

可以发现只有当两个序列中都没有重复元素时(1~n的排列)此种优化才是高效的,不然可能很不稳定。

求a[] 与b[]中的LCS
通过记录lis[i]表示a[i]在b[]中的位置,将LCS问题转化为最长上升子序列问题,转化方法如下:

for(int i=1;i<=n;i++){        local[b[i]]=i;    }    for(int i=1;i<=n;i++){        lis[i]=local[a[i]];    }

当序列中有元素重复时,我们们需要保证对于每个a[i]所记录的位置必须是逆序的,以保证一个元素只取一次。

例:举例说明:
A:abdba
B:dbaaba
则1:先顺序扫描A串,取其在B串的所有位置:
2:a(2,3,5) b(1,4) d(0)。
3:用每个字母的反序列替换,则最终的最长严格递增子序列的长度即为解。
替换结果:532 41 0 41 532

代码如下:

#include 
#include
#include
#include
#include
using namespace std;int read(){ int rv=0,fh=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); } while(c>='0'&&c<='9'){ rv=(rv<<1)+(rv<<3)+c-'0'; c=getchar(); } return fh*rv;}int n,a[100005],b[100005],local[100005],lis[100005],dp[100005];int main(){ freopen("in.txt","r",stdin); n=read(); for(int i=1;i<=n;i++){ a[i]=read(); } for(int i=1;i<=n;i++){ b[i]=read(); } for(int i=1;i<=n;i++){ local[b[i]]=i; } for(int i=1;i<=n;i++){ lis[i]=local[a[i]]; } dp[1]=lis[1];dp[0]++; for(int i=2;i<=n;i++){ int l=1,r=dp[0],m=0; while(l<=r){ m=(l+r)>>1; if(dp[m]<=lis[i]){ l=m+1; }else r=m-1; } if(l==1){ dp[l]=min(dp[l],lis[i]); }else { if(l==dp[0]+1){ dp[0]++; dp[l]=lis[i]; }else { dp[l]=min(dp[l],lis[i]); } } } cout<

转载于:https://www.cnblogs.com/Mr-WolframsMgcBox/p/7868363.html

你可能感兴趣的文章
如何利用python将.doc文件转换为.docx文件
查看>>
Ubuntu 14.04 定时任务
查看>>
切片对象
查看>>
[置顶] Android入门教程------导入现有Android工程
查看>>
《Entity Framework 6 Recipes》中文翻译系列 (40) ------ 第七章 使用对象服务之从跟踪器中获取实体与从命令行生成模型(想解决EF第一次查询慢的,请阅读)...
查看>>
Intro to Filtering with Network Monitor 3.0
查看>>
问卷调查
查看>>
Contest Record
查看>>
使用仓库管理器——Sonatype Nexus的九大理由
查看>>
51Nod 1066 - Bash游戏
查看>>
servlet session管理的四种方式--一 url重写
查看>>
术语解析之SAX
查看>>
PMSM 高性能电压补偿器
查看>>
linux中的文件解压命令
查看>>
运维与自动化运维发展方向
查看>>
txt,csv,json互相转化
查看>>
Codeforces Round #358 (Div. 2) C. Alyona and the Tree DFS
查看>>
节点遍历 element traversal
查看>>
nginx php 安装配置
查看>>
java用double和float进行小数计算精度不准确
查看>>