問題描述
東東有兩個序列A和B。
他想要知道序列A的LIS和序列AB的LCS的長度。
注意,LIS爲嚴格遞增的,即a1<a2<…<ak(ai<=1,000,000,000)。
Input
第一行兩個數n,m(1<=n<=5,000,1<=m<=5,000)
第二行n個數,表示序列A
第三行m個數,表示序列B
Output
輸出一行數據ans1和ans2,分別代表序列A的LIS和序列AB的LCS的長度
解題思路
這個題是基本的動態規劃問題,LIS是最長上升子序列,LCS是最長公共子序列。
求解LIS就是設dp[i]爲以當前元素結尾的最長上升序列,那麼,最終答案就是。
而求解LCS則是遍歷兩個序列,設是到第一個序列的第個元素,第二個序列的第個元素爲止,最長的公共子序列。如果,那麼我們就有,否則有。因此最終結果是。
完整代碼
//#pragma GCC optimize(2)
//#pragma G++ optimize(2)
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn=5000+10;
int n,m,a[maxn],b[maxn],dp1[maxn],dp2[maxn][maxn],ans;
int getint(){
int x=0,s=1; char ch=' ';
while(ch<'0' || ch>'9'){ ch=getchar(); if(ch=='-') s=-1;}
while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar();}
return x*s;
}
int main(){
//ios::sync_with_stdio(false);
//cin.tie(0);
n=getint(); m=getint();
for (int i=1; i<=n; i++) a[i]=getint(),dp1[i]=1;
for (int i=1; i<=m; i++) b[i]=getint();
for (int i=1; i<=n; i++){
for (int j=1; j<i; j++)
if(a[j]<a[i]) dp1[i]=max(dp1[i],dp1[j]+1);
ans=max(ans,dp1[i]);
}
for (int i=1; i<=n; i++){
for (int j=1; j<=m; j++){
if(a[i]==b[j]) dp2[i][j]=dp2[i-1][j-1]+1;
else dp2[i][j]=max(dp2[i-1][j],dp2[i][j-1]);
}
}
printf("%d %d\n",ans,dp2[n][m]);
return 0;
}