题目链接: https://www.luogu.com.cn/problem/P1439
题目描述
给出 1,2,…,n 的两个排列 P1 和 P2 ,求它们的最长公共子序列。
输入格式
第一行是一个数 n。
接下来两行,每行为 n 个数,为自然数 1,2,…,n 的一个排列。
输出格式
一个数,即最长公共子序列的长度。
输入输出样例
输入 #1复制
5 3 2 1 4 5 1 2 3 4 5输出 #1复制
3说明/提示
- 对于 50\%50% 的数据, n≤10^3;
- 对于 100\%100% 的数据, n <= 10^5。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
//解题思路:
//解法二O(nlog2n):
//由于两串值都一样,将一个串离散化成升序1-n
//则在读入另一串时,按照离散化顺序后的最长递增序列则是最大公共子串
#define max(x, y) (x) > (y)? (x) : (y);
inline void read(int &x)
{
register int f = 1;
x = 0;
register char c = getchar();
while(c > '9' || c < '0')
{
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
{
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
x *= f;
}
const int maxn = 1e4 + 5;
int a[maxn], b[maxn];
int d[maxn], to[maxn];
//先读入一串,并且按1-n顺序离散化
void input(const int &n)
{
for(int i = 1; i <= n; i++)
{
read(a[i]);
// 离散化
to[a[i]] = i;
}
}
int main()
{
int n, len(0); read(n);
input(n);
for(int i = 1; i <= n; i++)
{
read(b[i]);
// 按离散化之后的顺序,得到最长递增序列的长度
int t = to[b[i]];
if(t > d[len])
{
d[++len] = t;
}
else
{
int s = lower_bound(d + 1, d + len + 1, t) - d;
d[s] = t;
}
}
printf("%d\n", len);
return 0;
}
//解法一:
//int dp[maxn][maxn];
//int main()
//{
// int n; read(n);
// input(n);
// for(int i = 1; i <= n; i++)
// {
// for(int j = 1; j <= n; j++)
// {
// if(a[i] == b[j])
// {
// dp[i][j] = dp[i - 1][j - 1] + 1;
// }
// else
// {
// dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
// }
// }
// }
// printf("%d\n", ans);
// return 0;
//}