排列LCS问题

本文介绍了一种求解两个排列的最长公共子序列问题的方法,通过转化成最长不降子序列问题并使用二分查找来优化算法,适用于数据规模n≤100000的情况。

题目描述

给出1-n的两个排列P1和P2,求它们的最长公共子序列。

输入输出格式

输入格式:
第一行是一个数n,

接下来两行,每行为n个数,为自然数1-n的一个排列。

输出格式:
一个数,即最长公共子序列的长度

输入输出样例

输入样例#1:
5
3 2 1 4 5
1 2 3 4 5
输出样例#1:
3
说明

【数据规模】

对于50%的数据,n≤1000

对于100%的数据,n≤100000

简要分析:将原问题通过排列中各元素的对应关系,转化为求序列中最长不降子序列问题 二分查找维护d数组 期望复杂度O(nlogn).

program lcs;
var
  n,i,j,l,r,mid,cnt,p,tem:longint;
  b,d,c:array[0..100000] of longint;
function search(x,y,k:longint):longint;
var l,r,mid:longint;
begin
  l:=x; r:=y;
  while l<>r do
   begin
     mid:=(l+r) shr 1;
     if d[mid]>k then r:=mid
     else
     if d[mid]<k then l:=mid+1;
   end;
  exit(r);
end;
begin
  readln(n);
  for i:=1 to n do
   begin
    read(tem);
    c[tem]:=i;  //c数组为下标数组
   end;
  for i:=1 to n do
   begin
    read(tem);
    b[i]:=c[tem];
   end;
  cnt:=1;
  fillchar(d,sizeof(d),0);
  d[1]:=b[1];
  for i:=2 to n do
   begin
     if b[i]>d[cnt] then
      begin
       inc(cnt);
       d[cnt]:=b[i]
      end
     else
     if b[i]<d[1] then d[1]:=b[i]
     else
      begin
       p:=search(1,cnt,b[i]);
       d[p]:=b[i];
      end;
   end;
 writeln(cnt);
end.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值