贼有意思[最长上升公共子序列](SAC大佬测试题)

时间:2023-03-09 13:21:42
贼有意思[最长上升公共子序列](SAC大佬测试题)

题目描述
Awson 最近越来越蠢了,一天就只知道 zyys。
他定义了一个 zyys 数列:这个数列满足:
1.是另外两个数列 A,B 的公共子序列;
2.数列单调递增。
现在他有一个问题,我们假设知道两个长度均为 N 的序列 A,B,如何去找最长的 zyys
数列呢?由于他只会 zyys 了,他把这个问题交给了你。
输入格式
第一行包含一个整数 N,表示序列 A,B 的长度;
接下来 2 行,每行 N 个数,表示序列 A,B。
输出格式
一行,输出最长的 zyys 数列。
输入样例
5
2 3 3 3 4
2 3 3 4 5
输出样例
3
数据范围
对于 50%的数据,有 N <= 50
对于 100%的数据,有 N <= 5000

50分:

f[i][j]=f[i'][j']  (a[i]==b[j],a[i']<a[i],a[i']==b[j'],i'<i,j'<j)

复杂度为O(n^4)

100分,只要稍作修改

我们令 f[i][j]表示A[1~i]以 B[j]为最后该序列的最后一个数的最长长度。

如果a[i]==b[j]则f[i][j]=maxlen(f[i-1][j'])+1   (a[i]>b[j'],j'<j)

否则显然f[i][j]=f[i-1][j]

maxlen那一部分边循环边更新就行了

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
int a[],b[];
int f[][],ans;
int main()
{
int i,j,k,l;
cin>>n;
for (i=; i<=n; i++)
{
scanf("%d",&a[i]);
}
for (i=; i<=n; i++)
{
scanf("%d",&b[i]);
}
for (i=; i<=n; i++)
{
int len=;
for (j=; j<=n; j++)
{
if (a[i]==b[j]) f[i][j]=len+;
else f[i][j]=f[i-][j];
if (a[i]>b[j]&&f[i-][j]>len) len=f[i-][j];
ans=max(ans,f[i][j]);
}
}
cout<<ans;
}