题目大意:
给定两个数字数组a[] , b[],在这两个数组中找一个最长的公共上升子序列,输出最长的长度
从别人地方copy的= = LCIS理解:
(1)f[i][j] 表示 a的前i,和b串前 j,以b[j]结尾的LCIS的长度;
if(a[i]!=b[j) f[i][j]=f[i-1][j];
else f[i][j]=max(f[i-1][k]+1) 1<=k<j&&b[k]<b[j];
O(n^3)的复杂度,因为多了一维k,但f[i-1][k]的最大值显然可以在处理i-1的时候求出来
for(i=1;i<=n;i++)
maxn=0;
for(j=1;j<=m;j++)
f[i][j]=f[i-1][j];
if(a[i]>b[j]&&maxn<f[i-1][j]) maxn=f[i-1][j];
if(a[i]==b[j]) f[i][j]=maxn+1;
最后扫一遍f[n][1......m] ,取最大值。
(2)压缩空间,时间不变:
用f[j]表示 所有的a[i]和b的前j个,以b[j]结尾的LCIS的长度。
注意到(1)中, if(a[i]>b[j]&&maxn<f[i-1][j]) maxn=f[i-1][j]; 我们取得其实是f[1..i-1][j]的最大值,那不就是f[j]吗?
int f[N];
int a[M],b[N];
memset(f,0,sizeof(f));
for(i=1;i<=M;i++)
maxn=0;
for(j=1;j<=N;j++)
if(a[i]>b[j]&&maxn<f[j]) maxn=f[j];
if(a[i]==b[j]) f[j]=maxn+1;
最后扫一遍f[1......N];
1 #include <cstdio> 2 #include <cstring> 3 4 using namespace std; 5 const int N = 1005; 6 #define max(a,b) a>b?a:b 7 int dp[N] , a[N] , b[N]; 8 /*可以看作是每次在第一个数据中提取一个数字,然后在第二个数组中 9 根据相同的数字来查找最长上升子序列,f[i][j],表示a[]前i个数据和 10 b数组前j个数据中能找到的以a[i]结尾的最长上升子序列的长度 11 但是因为下一行总是和前面所有行有关,不断更新找到前j个位置以某一个数结尾 12 的最大值,如果还是采用二维的,我们必须 13 if(a[i] == b[j])的时候,回过去建立 14 for(t = 1 ; t<i ; t++) 15 dp[i][j] = max(dp[i][j] , dp[t][k]+1); 16 复杂度就变成了n的3次方 17 这里压缩为1维数组的同时,不断更新到第j个位置所能达到的最大值 18 */ 19 void LCIS(int m , int n) 20 { 21 memset(dp , 0 , sizeof(dp)); 22 for(int i = 1 ; i<=m ; i++){ 23 /* 24 对于任意的f[i],f[j]来说,只要i>j,那么f[i]>f[j]的 25 这里k就是用来不断更新到离i最近的一个满足上升的位置 26 这样从离它最近的位置处进行更新这样得到的数据一定是 27 满足最优子结构的 28 比如2 , 3 , 5三个数,当把5加进来,直接用f[2]+1即可, 29 因为f[1]<=f[2]这是必定的,所以没必要执行f[1]+1,这样 30 就取消了重叠子结构的计算 31 */ 32 int k = 0; 33 for(int j = 1 ; j<=n ; j++){ 34 if(a[i] == b[j]) dp[j] = max(dp[j] , dp[k] + 1); 35 //只有大于的时候才更新k,表示离它最近的满足的最长上升子序列的位置 36 if(a[i] > b[j] && dp[k] < dp[j]) k = j; 37 } 38 } 39 } 40 41 int main() 42 { 43 int m , n , T; 44 scanf("%d" , &T); 45 while(T--){ 46 scanf("%d" , &m); 47 for(int i = 1 ; i<=m ; i++) 48 scanf("%d" , a+i); 49 50 scanf("%d" , &n); 51 for(int i= 1 ; i<=n ; i++) 52 scanf("%d" , b+i); 53 54 LCIS(m , n); 55 int maxn = 0; 56 for(int i = 1 ; i <= n ; i++) 57 maxn = max(maxn , dp[i]); 58 59 printf("%d " , maxn); 60 if(T>0) puts(""); 61 } 62 return 0; 63 }