Greatest Common Increasing Subsequence
Description
You are given two sequences of integer numbers. Write a program to determine their common increasing subsequence of maximal possible length.
Sequence S 1 , S 2 , . . . , S N of length N is called an increasing subsequence of a sequence A 1 , A 2 , . . . , A M of length M if there exist 1 <= i 1 < i 2 < . . . < i N <= M such that S j = A ij for all 1 <= j <= N , and S j < S j+1 for all 1 <= j < N . Input
Each sequence is described with M --- its length (1 <= M <= 500) and M integer numbers A
i (-2
31 <= A
i < 2
31 ) --- the sequence itself.
Output
On the first line of the output file print L --- the length of the greatest common increasing subsequence of both sequences. On the second line print the subsequence itself. If there are several possible answers, output any of them.
Sample Input 5 1 4 2 5 -12 4 -12 1 2 4 Sample Output 2 1 4 Source
Northeastern Europe 2003, Northern Subregion
|
题意:
给出两个序列a、b,求最长公共递增子序列。
思路:
dp[j]表示以b[j]结尾的LCIS的长度。
每次用a[i]去更新dp[j],则
if(a[i]==b[j]) dp[j]=max(dp[j],dp[k]); (1<=k<j&&b[k]<b[j])
维护好k的值,那么就可以将复杂度降到O(n*m)了。
由于要记录路径,用一维的dp、pre不太好处理,我用的是二维的,递归输出路径。
思路来源:推荐
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 1005 #define MAXN 100005 #define mod 100000000 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 typedef long long ll; using namespace std; int n,m,k,ans,cnt,tot,flag; int ai,aj; int a[505],b[505]; int dp[505][505],px[505][505],py[505][505]; void output(int x,int y,int last) { if(x==0||y==0) return ; output(px[x][y],py[x][y],y); if(y!=last) { cnt++; if(cnt==1) printf("%d",b[y]); else printf(" %d",b[y]); } } void solve() { int i,j,k,t; memset(dp,0,sizeof(dp)); memset(px,0,sizeof(px)); memset(py,0,sizeof(py)); ans=0; for(i=1;i<=n;i++) { k=0; for(j=1;j<=m;j++) { dp[i][j]=dp[i-1][j]; px[i][j]=i-1,py[i][j]=j; if(b[j]==a[i]) { if(dp[i][j]<dp[i][k]+1) { dp[i][j]=dp[i][k]+1; px[i][j]=i,py[i][j]=k; } } else if(b[j]<a[i]) { if(dp[i][k]<dp[i][j]) k=j; } if(dp[i][j]>ans) { ans=dp[i][j]; ai=i,aj=j; } } } printf("%d\n",ans); if(ans==0) return ; cnt=0; output(ai,aj,-1); printf("\n"); } int main() { int i,j,t; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) { scanf("%d",&a[i]); } scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d",&b[i]); } solve(); } return 0; } /* 7 1 2 4 0 1 4 5 6 0 3 1 2 4 5 */