Codeforces [10D] LCIS [Longest common ascending subsequence]

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:

dp[i,j] Expressed  A_1...A_i and  B_1...B_j to be composed of  B_j a length of the end LCIS.

When  A_i \neq B_j the time has dp[i,j]=dp[i-1,j]

When  A_i = B_j the time has dp[i,j]=\max_{0\leq k< j,B_k<B_j}(dp[i-1,k])+1

Here, because enumerating k, it O (n ^ 3) will time out, so optimize it.

Record [0, all j),  B_k<B_jthe  dp[i-1,k]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  O (n ^ 2).

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;
}

 

Published 30 original articles · won 5 · 900 views

Guess you like

Origin blog.csdn.net/qq_42840665/article/details/104055450