Description
The sequence a1, a2, ..., an is called increasing, if ai < ai + 1 for i < n.
The sequence s1, s2, ..., sk is called the subsequence of the sequence a1, a2, ..., an, if there exist such a set of indexes 1 ≤ i1 < i2 < ... < ik ≤ n that aij = sj. In other words, the sequence s can be derived from the sequence a by crossing out some elements.
You are given two sequences of integer numbers. You are to find their longest common increasing subsequence, i.e. an increasing sequence of maximum length that is the subsequence of both sequences.
Input
The first line contains an integer n (1 ≤ n ≤ 500) — the length of the first sequence. The second line contains n space-separated integers from the range [0, 10^9] — elements of the first sequence. The third line contains an integer m (1 ≤ m ≤ 500) — the length of the second sequence. The fourth line contains m space-separated integers from the range [0, 10^9] — elements of the second sequence.
Output
In the first line output k — the length of the longest common increasing subsequence. In the second line output the subsequence itself. Separate the elements with a space. If there are several solutions, output any.
Examples
input
7
2 3 1 6 5 4 6
4
1 3 5 6
output
3
3 5 6
input
5
1 2 0 2 1
3
1 0 1
output
2
0 1
The main idea:
Given arrays A and B whose length is less than or equal to 500, find their longest common ascending subsequence.
analysis:
Expressed
and
to be composed of
a length of the end LCIS.
When the time has
When the time has
Here, because enumerating k, it will time out, so optimize it.
Record [0, all j), the
maximum value used to query directly, then we put i as the outermost loop, constantly maintain this maximum, then you can put the time complexity down
.
See the code for specific explanation.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 500 + 5;
int dp[maxn][maxn],p[maxn][maxn];
int a[maxn],b[maxn];
vector<int> v;
int n,m,ans,path;
void LCIS(int a[],int n,int b[],int m){
for(int i=1;i<=n;i++){//外层循环
int maxlen=0,pre=0;//maxlen代表dp[i-1][k]中的最大值,pre代表当前maxlen下的前一个B序列中选出的值(记录路径)
for(int j=1;j<=m;j++){
//这里假设Ai和Bj不等
dp[i][j]=dp[i-1][j];
p[i][j]=p[i-1][j];
if(a[i]==b[j]&&dp[i][j]<maxlen+1){//更新dp[i][j]和p[i][j]
dp[i][j]=maxlen+1;
p[i][j]=pre;
}
if(b[j]<a[i]&&dp[i-1][j]>maxlen){//更新maxlen和pre
maxlen=dp[i-1][j];
pre=j;
}
}
}
}
void Print(int pa) {//打印路径
if(!pa) return;
Print(p[n][pa]);
cout<<b[pa]<<" ";
}
int main() {
memset(dp,0,sizeof(dp));
memset(p,0,sizeof(p));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
}
LCIS(a,n,b,m);
//选出最长路径
for(int i=1;i<=m;i++){
if(ans<dp[n][i]){
ans=dp[n][i];
path=i;
}
}
printf("%d\n",ans);
Print(path);
return 0;
}