P1439 【模板】最长公共子序列
作者:互联网
题目链接
思路
第一种 $O(N^2)$
用f[i][j]表示第一个排列取到i位和第2个排列取到j位的公共子序列长度
$$f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1])$$
最后一种情况需满足$a[i]==b[i]$
对于$50%$的数据,$n≤1000$,应该可以过
第二种 $O(n \cdot log(n) )$
把a重新标号$1$到$n$,把b中和a相同的元素跑一遍最长上升子序列就好了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
using namespace std;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int n;
int a[100005],lcs[100005];
signed main()
{
cin>>n;
for(int i=1;i<=n;++i)
{
int x;
cin>>x;
a[x]=i;//标记
}
int len=0;
lcs[0]=-999;
for(int i=1;i<=n;++i)
{
int x;
cin>>x;
int now=a[x];
if(now>lcs[len])
{
lcs[++len]=now;
}
else
{
int j=lower_bound(lcs+1,lcs+len+1,now)-lcs;
lcs[j]=now;
}
}
cout<<len;
return 0;
}
关于lower_bound请看这篇博客点这里
手打二分的代码:
来自liuzitong
#include<bits/stdc++.h>
//#include<windows.h>
using namespace std;
int a[100001],c[100001],s;
int main(int argc, char const *argv[])
{
int n,xx;
a[0] = -100000;
cin>>n;
for (int i = 1; i <= n; ++i)
{
scanf("%d",&xx);
a[xx] = i;
}
int t;
for (int i = 1; i <= n; ++i)
{
scanf("%d",&t);
t = a[t];
if (t > c[s])
{
c[++s] = t;
}
else{
int l = 1,h = s,m;
while(l <= h){
m = (l + h) / 2;
if(t > c[m]) l =m + 1;
else h = m - 1;
}
c[l] = t;
}
}
cout<<s<<endl;
return 0;
// for (int i = 2; i <= n; ++i)
// {
// for (int j = 1; j < i; ++j)
// {
// if (b[i] > b[j] && c[i] < c[j] + 1)
// {
// c[i] = c[j] + 1;
// }
// }
// }
}
标签:now,lcs,int,len,else,P1439,序列,include,模板 来源: https://www.cnblogs.com/pyyyyyy/p/10910493.html