状态转移:当 s1[i-1]!=s2[j-1]时,按照lcs可知由2个状态转移过来,dp[i-1][j],dp[i][j-1],因为dp[i][j]是以s2[j]为结尾构成的LCIS的长度。所以s2[j-1]一定会包含在里面,所以舍去dp[i][j-1],只由dp[i-1][j] 转移过来。当s1[i-1]==s2[j-1],这时肯定要找前面s1[ii-1]==s2[jj-1]的最长且比s2[j-1]小的状态转移过来.
若s1[i-1]!=s2[j-1] 那么dp[i][j]=dp[i][j-1]
若s1[i-1]==s2[j-1] 那么dp[i][j]=MAX{dp[i-1][k]+1(0<k<j),s2[k-1]<s2[j-1]};
这里有一步可以优化就是求上一层的最值,可以在更新的同时就求出来,这样就从o(n^3)优化到o(n^2);时间上就是上10倍的差距。
Run ID | User | Problem | Result | Memory | Time | Language | Code Length | Submit Time |
9238676 | 201030720425 | 2127 | Accepted | 2168K | 1000MS | C++ | 1080B | 2011-08-27 00:32:56 |
9238626 | 201030720425 | 2127 | Accepted | 2168K | 79MS | C++ | 989B | 2011-08-27 00:09:30 |
#include<cstdio> #include<string> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> using namespace std; int n,m,rd[505][505],dp[505][505]; int s1[505],s2[505]; void DP() { int mac=0,ans=0,I,J,lu[505],mx; for(int i=1;i<=n;i++) { mx=0; for(int j=1;j<=m;j++) { int tem=dp[i][j]=dp[i-1][j]; if(mx<tem&&s1[i-1]>s2[j-1]) { mx=tem; mac=j; } if(s1[i-1]==s2[j-1]) { dp[i][j]=mx+1; rd[i][j]=mac; } if(ans<dp[i][j]) { ans=dp[i][j]; I=i,J=j; } } } printf("%d\n",ans); int len=ans; if(ans>0) lu[ans--]=J-1; while(ans&&I&&J) { if(rd[I][J]>0) { lu[ans--]=rd[I][J]-1; J=rd[I][J]; } I--; } for(int i=1;i<=len;i++) { printf("%d ",s2[lu[i]]); } printf("\n"); } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&s1[i]); scanf("%d",&m); for(int i=0;i<m;i++) scanf("%d",&s2[i]); DP(); return 0; }