1. LIS (Longest Increasing Subsequence)

O (n^2):

/*
LIS(Longest Increasing Subsequence) 最长上升子序列 O (n ^ 2)
状态转移方程:dp[i] = max (dp[j]) + 1 (a[j] < a[i],1 <= j < i)
附带有print输出路径函数
*/
void LIS(void) {
int ret = 0, last = 0;
for (int i=1; i<=n; ++i) {
dp[i] = 1; fa[i] = -1;
for (int j=1; j<i; ++j) {
if (a[j] < a[i] && dp[i] < dp[j] + 1) {
dp[i] = dp[j] + 1; fa[i] = j;
}
}
if (ret < dp[i]) {
ret = dp[i]; last = i;
}
} printf ("%d\n", ret);
print (last); puts ("");
} void print(int x) {
if (fa[x] != -1) {
print (fa[x]); printf (" %d", a[x]);
}
else printf ("%d", a[x]);
}

O (nlogn):

/*
LIS 二分查找优化, O(nlogn)
设当前最长递增子序列为len,考虑元素a[i]; 若d[len]<a[i],则len++,并使d[len]=a[i];
否则,在d[1~len]中二分查找第一个大于等于a[i]的位置j,使d[j]=a[i]。附上打印路径代码(准确性未知)
*/
void LIS(void) {
int len = 1; d[1] = a[1]; fa[1] = -1;
for (int i=2; i<=n; ++i) {
if (d[len] < a[i]) {
d[++len] = a[i];
pos[len] = i; fa[i] = pos[len-1];
}
else {
int j = lower_bound (d+1, d+1+len, a[i]) - d;
d[j] = a[i];
pos[j] = i; fa[i] = (j == 1) ? -1 : pos[j-1];
}
}
printf ("%d\n", len);
vector<int> res; int i;
for (i=pos[len]; ~fa[i]; i=fa[i]) res.push_back (a[i]);
res.push_back (a[i]);
for (int i=res.size ()-1; i>=0; --i) printf ("%d%c", res[i], i == 0 ? '\n' : ' ');
}

2. LCS (Longest Common Subsequence)

/*
LCS(Longest Common Subsequence):
状态转移方程:dp[i][j] = dp[i-1][j-1] + 1; (s[i-1] == t[i-1])
dp[i][j] = max (dp[i][j-1], dp[i-1][j]);(s[i-1] != t[i-1])
可滚动数组优化。附带有print输出路径函数。
*/
void LCS(void) {
memset (dp, 0, sizeof (dp));
memset (fa, 0, sizeof (fa));
for (int i=0; i<=lens; ++i) fa[i][0] = -1;
for (int i=0; i<=lent; ++i) fa[0][i] = 1; for (int i=1; i<=lens; ++i) {
for (int j=1; j<=lent; ++j) {
if (s[i-1] == t[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
fa[i][j] = 0;
}
else if (dp[i-1][j] >= dp[i][j-1]) {
dp[i][j] = dp[i-1][j];
fa[i][j] = -1;
}
else {
dp[i][j] = dp[i][j-1];
fa[i][j] = 1;
}
}
} printf ("%d\n", dp[lens][lent]);
print (lens, lent); puts ("");
} void print(int x, int y) {
if (!x && !y) return ;
if (fa[x][y] == 0) {
print (x-1, y-1); printf ("%c", s[x-1]);
}
else if (fa[x][y] == -1) {
print (x-1, y); printf ("%c", s[x-1]);
}
else {
print (x, y-1); printf ("%c", t[y-1]);
}
}

3. LCIS (Longest Common Increasing Subsequence)

/*
LCIS(Longest Common Increasing Subsequence) 最长公共上升子序列
状态转移方程:a[i] != b[j]: dp[i][j] = dp[i-1][j];
a[i] == b[j]: dp[j]=max(dp[j],dp[k]); (1<=k<j&&b[k]<b[j])  
打印路径时按照b[i]来输出
*/
void LCIS(void) {
memset (dp, 0, sizeof (dp));
memset (fx, 0, sizeof (fx));
memset (fy, 0, sizeof (fy));
int sx = 0, sy = 0;
int ret = 0, k = 0;
for (int i=1; i<=n; ++i) {
k = 0;
for (int j=1; j<=m; ++j) {
dp[i][j] = dp[i-1][j]; //以a[]为主循环,每个a[i],去找每个b[j]
fx[i][j] = i - 1; fy[i][j] = j;
if (a[i] == b[j] && dp[i][j] < dp[i][k] + 1) { //满足LCS
dp[i][j] = dp[i][k] + 1; //在1~j-1找到b[k]<a[i],满足LIS,在b[k]上更新dp
fx[i][j] = i; fy[i][j] = k;
}
else if (a[i] > b[j] && dp[i][j] > dp[i][k]) k = j; //找到最优的k
if (ret < dp[i][j]) {
ret = dp[i][j]; //更新所有dp中的最大值
sx = i, sy = j;
}
}
}
printf ("%d\n", ret);
fir = true;
print (sx, sy, -1); puts ("");
} void print(int x, int y, int last) { //bool fir;
if (x == 0 || y == 0) return ;
print (fx[x][y], fy[x][y], y);
if (y != last) {
if (fir) printf ("%d", b[y]), fir = false;
else printf (" %d", b[y]);
}
}

4. LPS (Longest Palidromic Subsequence)

/*
LCS的思想,dp[i][j]表示i到j的最长回文串长度,状态转移方程:
1. dp[j][j+i-1] = dp[j+1][j+i-2] + 2; (str[j] == str[j+i-1])
2. dp[j][j+i-1] = max (dp[j+1][j+i-1], dp[j][j+i-2]); (str[j] != str[j+i-1])
ans[1][len]是string类型,记录LPS字符
*/
void LPS(void) {
int len = strlen (str + 1);
memset (dp, 0, sizeof (dp));
for (int i=1; i<=len; ++i) dp[i][i] = 1;
for (int i=1; i<=len; ++i) ans[i][i] = str[i]; for (int i=2; i<=len; ++i) { //区间长度
for (int j=1; j+i-1<=len; ++j) { //[j, j+i-1]
if (str[j] == str[j+i-1]) {
if (i == 2) {
dp[j][j+i-1] = 2;
ans[j][j+i-1] = ans[j][j] + ans[j+i-1][j+i-1]; continue;
}
dp[j][j+i-1] = dp[j+1][j+i-2] + 2;
ans[j][j+i-1] = str[j] + ans[j+1][j+i-2] + str[j+i-1];
}
else if (dp[j+1][j+i-1] > dp[j][j+i-2]) {
dp[j][j+i-1] = dp[j+1][j+i-1];
ans[j][j+i-1] = ans[j+1][j+i-1];
}
else if (dp[j][j+i-2] > dp[j+1][j+i-1]) {
dp[j][j+i-1] = dp[j][j+i-2];
ans[j][j+i-1] = ans[j][j+i-2];
}
else {
dp[j][j+i-1] = dp[j+1][j+i-1];
ans[j][j+i-1] = min (ans[j+1][j+i-1], ans[j][j+i-2]);
}
}
}
int mlen = dp[1][len];
for (int i=0; i<mlen; ++i) {
printf ("%c", ans[1][len][i]);
}
puts ("");
}

5. MCS (Maximum Continuous Subsequence)

O (n):

/*
MCS (Maximum Continuous Subsequence) 最大子序列和 O (n)
1. DP 2. 前缀
若有多个答案输出第一个,均给出区间端点
*/
void MCS(int n) {
int l = 0, ll = 0, rr = 0;
int sum = -INF, mx = -INF;
for (int i=1; i<=n; ++i) {
if (sum + a[i] < a[i]) {
sum = a[i]; l = i;
}
else sum += a[i];
if (sum > mx) {
mx = sum; ll = l, rr = i;
}
}
printf ("%d %d %d\n", mx, ll, rr);
}

O (n) another:

//O (n) //another
void MCS(int n) {
int l = 0, ll = 0, rr = 0;
int sum = 0, mx = -INF, mn = 0;
for (int i=1; i<=n; ++i) {
sum += a[i];
if (sum - mn > mx) {
mx = sum - mn; ll = l; rr = i;
}
if (sum < mn) {
mn = sum; l = i;
}
}
printf ("%d %d %d\n", mx, ll + 1, rr);
}

O (nlogn):

//O (nlogn)     //输出端点困难
int MCS(int *a, int l, int r) {
if (l == r) {
if (a[l] > 0) return a[l];
else return 0;
}
int mid = (l + r) >> 1;
int lmax = MCS (a, l, mid);
int rmax = MCS (a, mid + 1, r); int lbmax = 0, lbsum = 0;
for (int i=mid; i>=left; --i) { //之前写错了,应该是连续的
lbsum += a[i];
if (lbmax < lbsum) lbmax = lbsum;
}
int rbmax = 0, rbsum = 0;
for (int i=mid+1; i<=r; ++i) {
rbsum += a[i];
if (rbmax < rbsum) rbmax = rbsum;
} return max (lbmax + rbmax, max (lmax, rmax));
}

  

  

LIS && LCS && LCIS && LPS && MCS模板的更多相关文章

  1. LIS+LCS+LCIS

    PS:本篇博文均采用宏#define FOR(i, a, n) for(i = a; i <= n; ++i) LIS:最长上升子序列 废话不多说:http://baike.baidu.com/ ...

  2. 8.3 LIS LCS LCIS(完结了==!)

    感觉这个专题真不好捉,伤心了,慢慢啃吧,孩纸 地址http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28195#overview 密码  ac ...

  3. LIS LCS LCIS (主要过一遍,重在做题)

    只详细讲解LCS和LCIS,别的不讲-做题优先. 菜鸟能力有限写不了题解,可以留评论,我给你找博客. 先得理解最长上升子序列吧,那个HDOJ拦截导弹系列可以做一下,然后用o(n)log(n)的在做一遍 ...

  4. LIS&&LCS&&LCIS

    LIS #include<bits/stdc++.h> using namespace std; int n,a[100005],b[100005],ji; int main(){ cin ...

  5. 线性DP总结(LIS,LCS,LCIS,最长子段和)

    做了一段时间的线性dp的题目是时候做一个总结 线性动态规划无非就是在一个数组上搞嘛, 首先看一个最简单的问题: 一,最长字段和 下面为状态转移方程 for(int i=2;i<=n;i++) { ...

  6. LIS LCS n^2和nlogn解法 以及LCIS

    首先介绍一下LIS和LCS的DP解法O(N^2) LCS:两个有序序列a和b,求他们公共子序列的最大长度 我们定义一个数组DP[i][j],表示的是a的前i项和b的前j项的最大公共子序列的长度,那么由 ...

  7. LIS和LCS LCIS

    首先介绍一下LIS和LCS的DP解法O(N^2) LCS:两个有序序列a和b,求他们公共子序列的最大长度 我们定义一个数组DP[i][j],表示的是a的前i项和b的前j项的最大公共子序列的长度,那么由 ...

  8. LIS,LCS,LICS 学习笔记

    1.最长上升子序列(LIS) 子序列: 1.可以不连续 2.相对位置不变 dp[i][j] 表示前i位置,最大值为j的LIS长度 1. dp[i-1][j] 前i-1位置,最大值为j的LIS长度 (没 ...

  9. dp入门(LIS,LCS)

    LCS

随机推荐

  1. 继承LinearLayout实现根据屏幕宽度及内部子View个数自动排布GridView

    public class VerticalSearchGridView extends LinearLayout implements View.OnClickListener { private i ...

  2. 对FreeMarker技术的思考

    依照静态非静态来划分网页分为两种:静态网页和非静态网页,究其优缺点而言,静态网页在用户訪问的时候响应快,可是因为里面的数据是写死的.所以致命的缺陷就是数据不能动态显示.非静态页面(如jsp)数据能够动 ...

  3. 《从零開始学Swift》学习笔记(Day 61)——Core Foundation框架之内存管理

    原创文章,欢迎转载. 转载请注明:关东升的博客 在Swift原生数据类型.Foundation框架数据类型和Core Foundation框架数据类型之间转换过程中,尽管是大部分是能够零开销桥接,零开 ...

  4. java线程阻塞(sleep,suspend,resume,yield,wait,notify)

    为了解决对共享存储区的访问冲突,Java 引入了同步机制,现在让我们来考察多个线程对共享资源的访问,显然同步机制已经不够了,因为在任意时刻所要求的资源不一定已经准备好了被访问,反过来,同一时刻准备好了 ...

  5. Maven group, artifact or version defined in the pom file do not match the file ...

    在把library上传到bintray空间的时候报以下错误 Could not upload to 'https://api.bintray.com/content/ping/maven/comm-a ...

  6. 关于npm的环境变量配置、prefix

    1.关于npm 的 prefix 在npm中安装全局文件时,npm会把他安装在npm里面配置的prefix路径下,查看prefix的方法是:npm config list/npm config ls/ ...

  7. POJ1077 Eight —— 双向BFS

    主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html (代码一直在精简完善……) 代码一:两个BFS, 两段代码: 用step控制“你一步, 我一步 ...

  8. FMDB 使用技巧

    源链接:  http://blog.csdn.net/iunion/article/details/7091744 - (BOOL) isTableOK:(NSString *)tableName{  ...

  9. vue 更改头像功能实现

     ——————– 如上图所示:需要完成的功能是点击更改头像,获取本地文件库,选择图片后将原始图片替换.这里我就直接用html文件引入vue来简单实现在这功能,代码如下: HTML: <div i ...

  10. codeforces 454B. Little Pony and Sort by Shift 解题报告

    题目链接:http://codeforces.com/problemset/problem/454/B 题目意思:给出一个序列你 a1, a2, ..., an. 问每次操作只能通过将最后一个数拿出来 ...