贼有意思[最长上升公共子序列](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那一部分边循环边更新就行了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n; 7 int a[5001],b[5001]; 8 int f[5001][5001],ans; 9 int main() 10 { 11 int i,j,k,l; 12 cin>>n; 13 for (i=1; i<=n; i++) 14 { 15 scanf("%d",&a[i]); 16 } 17 for (i=1; i<=n; i++) 18 { 19 scanf("%d",&b[i]); 20 } 21 for (i=1; i<=n; i++) 22 { 23 int len=0; 24 for (j=1; j<=n; j++) 25 { 26 if (a[i]==b[j]) f[i][j]=len+1; 27 else f[i][j]=f[i-1][j]; 28 if (a[i]>b[j]&&f[i-1][j]>len) len=f[i-1][j]; 29 ans=max(ans,f[i][j]); 30 } 31 } 32 cout<<ans; 33 }