您的位置:首页 > 其它

洛谷p1439 最长公共子序列(绝密!最长公共子序列的本质居然是....)

2018-03-01 16:55 253 查看


题目描述

给出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

一开始学dp的时候就接触了最长公共子序列,当时觉得超简单啊,转移方程非常好理解,这几天刷水题的时候看到了立马就写了。但看到数据范围就蒙了= =(maye10^5!!)

但我还是超皮的用dp试了一下,结果就绿了两个点!!其他不是RE就是T( ' – ' ) (凉凉qwq)

下面是n方算法(二维数组都开不下的辣鸡算法QAQ)非常好理解就不多bb了orz

垂死挣扎了很久,还是没想出来nlogn的算法(啊我真菜)。然后看着那个窒息的二十分,我终于忍不住打开了题解。从打开题解到提交然后ac一共就五六分钟吧。

题解里的前排dalao讲的炒鸡清楚/////(以下是copy的dalao的题解。权侵删)

我们可以以第一个串为标准,用第二个串来匹配第一个串,看能匹配多少,所以,其实第一个串的每个数字其实影响不大,只有知道它对应了第二串的哪个数字就好了,那么我们为什么不把他给的串重新定义一下?

比如他的样例:3 2 1 4 5 我们把他变成 1 2 3 4 5 用一个数组记录一下每个数字变成了什么,相当于离散化了一下3-1;2-2;1-3;4-4;5-5;

现在我们的第二串1 2 3 4 5 按我们离散化的表示:3 2 1 4 5

然后就非常容易得到正确做法啦!没错!就是经典的最长不下降子序列(包含上升和相同)!

真的是万万没想到啊唔。总之,疯狂为nb的dalao们打call就对了!!

最后献上我的低龄化代码(〃ω〃)

```

#include <iostream>

#include <algorithm>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <cstring>

#include <queue>

#define maxi 0x7fffffff

using namespace std;

int n,x,ans;

int a[400000],b[400000],c[400000];

int main()

{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&x);
a[x]=i;
}
for(int i=1;i<=n;++i)
{
scanf("%d",&x);
b[i]=a[x];
}
c[0]=-0x7fffffff;
for(int i=1;i<=n;++i)
{
if(b[i]>=c[ans])
{
c[++ans]=b[i];
continue;
}
int l=0,r=ans;
while(l!=r)
{
int mid=(l+r)/2;
if(b[i]<c[mid])r=mid;
else l=mid+1;
}
c[l]=b[i];
}
printf("%d",ans);
return 0;

}

```

没p放啦,over!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息