LIS+LCS+LCIS
PS:本篇博文均采用宏#define FOR(i, a, n) for(i = a; i <= n; ++i)
- LIS:最长上升子序列
废话不多说:http://baike.baidu.com/link?url=bRXFb18sGwPcKpplIIIq40hnngEUJe6S4b1PLgVnaby8zaahrO2NhI2tfoQZmw54#2_1 http://www.nocow.cn/index.php/%E6%9C%80%E9%95%BF%E4%B8%8D%E4%B8%8B%E9%99%8D%E5%AD%90%E5%BA%8F%E5%88%97
设状态f(i)表示前i个数的最长上升子序列的长度,可以得到
f(i) = max{f(j)} + 1, 其中 1 <= j < i且a[i] < a[j]
答案就是max{f(i)}, 1<=i<=n
CODE:
FOR(i, 1, n) {
f[i] = 1; //初始化
FOR(j, 1, i-1)
if(a[j] < a[i] && f[i] < f[j] + 1)
f[i] = f[j] + 1, ans = max(ans, f[i]);
}其实就是在前面找一个k,接上去
然后是带路径记录的LIS,想法是,既然每次都是找f[j]来接到f[i]上,那么记录每个j,然后逆着走即可:
#include <cstdio>
using namespace std;
#define FOR(i, a, n) for(i = a; i <= n; ++i) const int maxn = 5000;
int n, a[maxn], f[maxn], i, j, ans;
int pre[maxn], path[maxn], pos, len; void setIO() {
freopen("in", "r", stdin);
freopen("out", "w", stdout);
}
int main() {
setIO();
scanf("%d", &n);
FOR(i, 1, n) scanf("%d", &a[i]);
FOR(i, 1, n) {
f[i] = 1; //初始化
FOR(j, 1, i-1) //增序得出来答案是lower_bound(i)的。。
if(a[j] < a[i] && f[i] < f[j] + 1) {
f[i] = f[j] + 1;
pre[i] = j; //记录接入的路径
if(ans < f[i])
ans = f[i], pos = i; //记录最长的开始下标
}
}
printf("%d\n", ans);
len = ans;
if(ans > 0) path[ans--] = pos; //先加入进去,因为没有记录最后的接入路径
while(ans && pos) {
if(pre[pos] > 0) {
path[ans--] = pre[pos];
pos = pre[pos];
}
}
FOR(i, 1, len) printf("%d ", a[path[i]]);
return 0;
} - LCS:最长公共子序列
还是去看nocow把:http://www.nocow.cn/index.php/%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97
设f(i, j)表示a的前i个数和b的前j个数的最大公共子序列长度,有
f(i, j) = f(i-1, j-1) + 1, a[i] == b[j]
f(i, j) = max{f(i-1, j), f(i, j-1)}, a[i] != b[j]
答案是f(sa, sb),sa,sb是a和b的长度
将这个用矩阵表示好理解,具体看nocow
二维:
FOR(i, 1, sa) FOR(j, 1, sb)
if(seq1[i] == seq2[j]) f[i][j] = f[i-1][j-1] + 1;
else f[i][j] = max(f[i-1][j], f[i][j-1]);由于是方程严格递增并且方程阶段是第二维,那么我们可以转化为一维的
一维:
FOR(i, 1, sa) FOR(j, 1, sb)
if(seq1[i] == seq2[j]) f[j] = f[j-1] + 1;
else f[j] = max(f[j], f[j-1]);那么用二维的我们还能求路径,与LIS不同的是,LCS求路径是方程的逆,逆回去即可。。。
可以用矩阵来想
for(i = sa, j = sb; j > 0 && i > 0;) {
if(seq1[i] == seq2[j]) {
path[num++] = seq1[i];
i--; j--;
}
else (f[i-1][j] > f[i][j-1]) ? i-- : j--;
}全套:
#include <cstdio>
#include <iostream>
using namespace std;
#define FOR(i, a, n) for(i = a; i <= n; ++i) void setIO() {
freopen("in", "r", stdin);
freopen("out", "w", stdout);
}
const int maxn = 500;
int i, j, num, f[maxn][maxn], seq1[maxn], seq2[maxn], sa, sb;
int path[maxn]; int max(const int& a, const int& b) { return a < b ? b : a; } int main() {
setIO(); scanf("%d%d", &sa, &sb);
FOR(i, 1, sa) scanf("%d", &seq1[i]);
FOR(i, 1, sb) scanf("%d", &seq2[i]);
FOR(i, 1, sa) FOR(j, 1, sb)
if(seq1[i] == seq2[j]) f[i][j] = f[i-1][j-1] + 1;
else f[i][j] = max(f[i-1][j], f[i][j-1]);
for(i = sa, j = sb; j > 0 && i > 0;) {
if(seq1[i] == seq2[j]) {
path[num++] = seq1[i];
i--; j--;
}
else (f[i-1][j] > f[i][j-1]) ? i-- : j--;
}
cout << f[sa][sb] << endl;
for(i = num-1; i >= 0; --i) cout << path[i] << ' ';
cout << endl;
return 0;
} - LCIS:最长公共上升子序列
这个可以说是LCS和LIS的结合体~。我们用LIS的思想来想,3维的方法我不会。。网上也没有找到,那就只有用n^2算法把。。
具体定义什么的可以参考前一篇博文
这里更新一下求路径的以及一些注释
#include <iostream>
#include <cstdio>
using namespace std; #define FOR(i, a, n) for(i = a; i <= n; ++i) void setIO() {
freopen("in", "r", stdin);
freopen("out", "w", stdout);
}
const int maxn = 550;
int seq1[maxn], seq2[maxn], sa, sb;
int f[maxn], pre[maxn][maxn], path[maxn], ans, len, maxi, temp, pos1, pos2, i, j, k;
int max(const int& a, const int& b) { return a < b ? b : a; } int main() {
setIO(); cin >> sa >> sb;
FOR(i, 1, sa) cin >> seq1[i];
FOR(i, 1, sb) cin >> seq2[i];
ans = 0;
FOR(i, 1, sa) {
maxi = temp = 0; //初始化,很重要
FOR(j, 1, sb) //求lcds将a[i] > b[j]改为a[i] < b[j]即可
if(seq1[i] > seq2[j] && f[j] > maxi) maxi = f[j], temp = j; //得到temp = max{f[i-1][k]}
else if(seq1[i] == seq2[j]) {
f[j] = maxi + 1;
pre[i][j] = temp; //能接上b[j]的b[temp],以后用答案直接索引到temp
if(ans < f[j]) {
pos1 = i; //记录最长公共上升seq所对应的下标i和j
pos2 = j;
ans = f[j];
}
}
}
cout << ans << endl;
len = ans;
//和LIS的路径几乎一模一样
if(ans > 0) path[ans--] = pos2; //将最后的添上
while(ans && pos1 && pos2) { //依据pos2(最长seq的j值)一直找
if(pre[pos1][pos2] > 0) {
path[ans--] = pre[pos1][pos2]; //将这些k记录下来
pos2 = pre[pos1][pos2]; //更新接上的最大
}
pos1--; //因为要的是max{f[i-1][k]},所以要倒着i-1回去找,即f[i-1][k],记录的k值
}
FOR(i, 1, len) cout << seq2[path[i]] << ' ';
cout << endl; return 0;
}
LIS+LCS+LCIS的更多相关文章
- 8.3 LIS LCS LCIS(完结了==!)
感觉这个专题真不好捉,伤心了,慢慢啃吧,孩纸 地址http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28195#overview 密码 ac ...
- LIS LCS LCIS (主要过一遍,重在做题)
只详细讲解LCS和LCIS,别的不讲-做题优先. 菜鸟能力有限写不了题解,可以留评论,我给你找博客. 先得理解最长上升子序列吧,那个HDOJ拦截导弹系列可以做一下,然后用o(n)log(n)的在做一遍 ...
- LIS && LCS && LCIS && LPS && MCS模板
1. LIS (Longest Increasing Subsequence) O (n^2): /* LIS(Longest Increasing Subsequence) 最长上升子序列 O (n ...
- LIS&&LCS&&LCIS
LIS #include<bits/stdc++.h> using namespace std; int n,a[100005],b[100005],ji; int main(){ cin ...
- 线性DP总结(LIS,LCS,LCIS,最长子段和)
做了一段时间的线性dp的题目是时候做一个总结 线性动态规划无非就是在一个数组上搞嘛, 首先看一个最简单的问题: 一,最长字段和 下面为状态转移方程 for(int i=2;i<=n;i++) { ...
- LIS LCS n^2和nlogn解法 以及LCIS
首先介绍一下LIS和LCS的DP解法O(N^2) LCS:两个有序序列a和b,求他们公共子序列的最大长度 我们定义一个数组DP[i][j],表示的是a的前i项和b的前j项的最大公共子序列的长度,那么由 ...
- LIS和LCS LCIS
首先介绍一下LIS和LCS的DP解法O(N^2) LCS:两个有序序列a和b,求他们公共子序列的最大长度 我们定义一个数组DP[i][j],表示的是a的前i项和b的前j项的最大公共子序列的长度,那么由 ...
- LIS,LCS,LICS 学习笔记
1.最长上升子序列(LIS) 子序列: 1.可以不连续 2.相对位置不变 dp[i][j] 表示前i位置,最大值为j的LIS长度 1. dp[i-1][j] 前i-1位置,最大值为j的LIS长度 (没 ...
- dp入门(LIS,LCS)
LCS
随机推荐
- 16.O(logn)求Fibonacci数列[Fibonacci]
[题目] log(n)时间Fib(n),本质log(n)求a^n. [代码] C++ Code 12345678910111213141516171819202122232425262728293 ...
- DFS:Lake Counting(POJ 2386)
好吧前几天一直没更新博客,主要是更新博客的确是要耗费一点精力 北大教你数水坑 最近更新博客可能就是一点旧的东西和一些水题,主要是最近对汇编感兴趣了嘻嘻嘻 这一题挺简单的,没什么难度,简单深搜 #inc ...
- hdu 1425 sort 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1425 常规的方法是对输入的数从大到小进行排序(可以用sort或qsort),然后输出前m大的数. 不过 ...
- Java性能优化权威指南-读书笔记(五)-JVM性能调优-吞吐量
吞吐量是指,应用程序的TPS: 每秒多少次事务,QPS: 每秒多少次查询等性能指标. 吞吐量调优就是减少垃圾收集器消耗的CPU周期数,从而将更多的CPU周期用于执行应用程序. CMS吞吐调优 CMS包 ...
- 基于gitosis的Git云端服务器配置
(本文需要自己实践,由于时间关系,我仅仅是做了整理和快速的练习,至于笔记中的账号和ip域名都是我参考文章中的.如果读者有任何问题欢迎留言和发邮件到luoquantao@126.com) 硬件:云端阿里 ...
- 火车站(codevs 2287)
题目描述 Description 火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车,但上.下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数 ...
- loadingDialog
1.dialog布局 dialog_loading.xml <?xml version="1.0" encoding="utf-8"?> <L ...
- 百万用户时尚分享网站feed系统扩展实践
Fashiolista是一个在线的时尚交流网站,用户可以在上面建立自己的档案,和他人分享自己的以及在浏览网页时看到的时尚物品.目前,Fashiolista的用户来自于全球100多个国家,用户达百万级, ...
- 关于Qt的事件循环以及QEventLoop的简单使用
1.一般我们的事件循环都是由exec()来开启的,例如下面的例子: 1 QCoreApplicaton::exec() 2 QApplication::exec() 3 QDialog::exec() ...
- Java Hour 58 Java Virtual Machine
每每谈到Java Virtual Machine, 你必须意识到这个有三种意思: 1 一个抽象的指南 2 一个具体的实现 3 一个运行时的实例 JVM 的生命周期 每个运行时JVM 实例都是为一个特定 ...