
by Oler 87
姓名:庄宇浩 学号:087
2000:最长公共子上升序列
总时间限制: 10000ms
内存限制: 65536kB
描述
给定两个整数序列,写一个程序求它们的最长上升公共子序列。
当以下条件满足的时候,我们将长度为N的序列S1 , S2 , . . . , SN 称为长度为M的序列A1 , A2 , . . . , AM 的上升子序列:
存在 1 <= i1 < i2 < . . . < iN <= M ,使得对所有 1 <= j <=N,均有Sj = Aij,且对于所有的1 <= j < N,均有Sj < Sj+1。输入
每个序列用两行表示,第一行是长度M(1 <= M <= 500),第二行是该序列的M个整数(-231 <= Ai < 231 )输出
在第一行,输出两个序列的最长上升公共子序列的长度L。在第二行,输出该子序列。如果有不止一个符合条件的子序列,则输出任何一个即可。样例输入
5
1 4 2 5 -12
4
-12 1 2 4
样例输出
2
1 4
题目分析
相较于典型的求最长子序列和求上升子序列问题,这道题综合了两道题的特点,需要求两个zx序列的最长公共子序列,具有更高的难度,也需要用升级版的DP算法解决.
这道题用向量解法很轻松.首先,程序中定义了一个结构体,其中包括一个整形向量w和向量中的元素个数val(初始值为零).然后输入两个数组a[501]和b[501],然后定义一个向量Max为最长公共子序列结构体.dp[501]作为交换值,作为中间变量.
关键是比较部分.比较部分基于b[i]在外,ap[j]在内的双重循环.if (b[i] > a[j] && dp[j].val > Max.val):如果b[i]大于a[j]而且dp结构体中的向量个数大于Max中的向量元素个数,就把dp[j]赋值给Max.
if (b[i] == a[j]):如果b[i]等于a[j],就把b[i]补到dp[j]向量的尾部,并且结构体中对应的元素个数加一.
最后是输出部分.开始把dp[1]赋值给Max,然后进行循环比较.一直比到dp[501],比出最大的那个,然后将其输出.
数据结构
两个一维整形数组,一个结构体数组,一个结构体变量.
代码及算法说明
#include<vector>
#include<iostream>
using namespace std;
struct Node { //定义结构体
int val = 0; //val指向量中含有的元素个数
vector<int>w; //指该向量为一维整形向量
};
int main() {
int a[501], b[501]; //两个比较数组
Node dp[501]; //记录公共子序列的中间值
int m, n; //数组中元素的个数
cin >> m; //cin函数相当于c语言中的scanf函数
for (int j = 1; j <= m; j++)
cin >> a[j];
cin >> n;
for (int j = 1; j <= n; j++)
cin >> b[j];
for (int i = 1; i <= n; i++)
{
Node Max; //max即为最长公共子序列
for (int j = 1; j <= m; j++) {
if (b[i] > a[j] && dp[j].val > Max.val) //判断条件:后一个数组元素值大于前一个并且对应数组元素个数比前一个多
Max = dp[j]; //将max赋值给元素个数更多的那个
if (b[i] == a[j]) {
dp[j].val = Max.val + 1;
dp[j].w = Max.w; //如果b[i] == a[j],则把b[i]补到dp[j]向量的尾部
dp[j].w.push_back(b[i]);
}
}
}
Node Max = dp[1]; //开始把max赋值给dp[1]
for (int i = 2; i <= m; i++) {
if (dp[i].val > Max.val) //对所有dp元素中的元素个数进行比较,并将max赋值给元素个数最多的那个
Max = dp[i];
}
cout << Max.val << endl;
for (int i = 0; i < Max.w.size(); i++)
cout << Max.w[i] << " "; //输出结构体max
cout << endl;
return 0;
}
算法分析
1.该算法有一部分参考了网上答案,其中的比较部分觉得很精炼,但是后来想了下觉得跟普通的比较算法差不多,注意要用向量的话要在头文件里加上#include<vector>
2.相较于数组,向量的优点在于:向量比较灵活,可以对向量中的元素进行添加和删除,能够有效的避免越界问题.而且对向量进行的函数操作更加方便.比如插入元素在 向量 中 只需要push_back函数,而在数组中则要用循环来赋值.
3.本代码中有许多细节很巧妙,比较部分可以大大减少代码长度,值得好好琢磨,并加以学习.
4.有不足之处们还请同学批评指正!