由于noi OJ上没有Special Judge,所以我是没有在这上面AC的。但是在POJ上A了。

题意如标题。

解法:f[i][j]表示a串前i个和b串前j个且包含b[j]的最长公共上升子序列长度

首先,可用3重循环得到,k循环找到b串j之前的最大长度子序列的结尾字符b[k],得以更新现在f[i][j]的状态。
然后,由于k循环的都在j之前,可发现k循环可略去,直接将满足上升的字符用临时变量存,每次j循环的都更新就好了。

具体上,最初f[i][j]=f[i-1][j],先继承好上一个状态,a[i]不加入选出的子序列(平常DP有表示“前...”的初始值都是像这样先可由前一个状态推出的)于是a[i]=b[j]时,就由之前存的最佳答案+1得到。最后由于这次的j是为了下次的a[i]=b[xx]做准备,所以若满足b[j]<a[i]且当前答案最佳,就更新临时储存的临时变量。

另外,打印路径有2种方法。用1维数组存是不行的,因为相同的一个i在和不同的j时,不能直接覆盖掉原来的答案。
1.用2个数组分别记录每次a[i]=b[j]之后ans+1的i和j;

  1. 1 #include<cstdio>
  2. 2 #include<cstdlib>
  3. 3 #include<cstring>
  4. 4 #include<iostream>
  5. 5 using namespace std;
  6. 6
  7. 7 typedef long long LL;
  8. 8 const int N=510;
  9. 9 LL a[N],b[N],s[N];
  10. 10 int f[N][N],u[N][N],v[N][N];
  11. 11
  12. 12 int main()
  13. 13 {
  14. 14 int n,m;
  15. 15 scanf("%d",&n);
  16. 16 for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
  17. 17 scanf("%d",&m);
  18. 18 for (int i=1;i<=m;i++) scanf("%lld",&b[i]);
  19. 19 memset(f,0,sizeof(f));
  20. 20 memset(u,0,sizeof(u));
  21. 21 memset(v,0,sizeof(v));
  22. 22 for (int i=1;i<=n;i++)
  23. 23 {
  24. 24 int p=0,q=0;
  25. 25 for (int j=1;j<=m;j++)
  26. 26 {
  27. 27 f[i][j]=f[i-1][j];
  28. 28 u[i][j]=u[i-1][j],v[i][j]=v[i-1][j];
  29. 29 if (a[i]==b[j]) f[i][j]=f[p][q]+1,u[i][j]=p,v[i][j]=q;
  30. 30 else if (a[i]>b[j] && f[i][j]>f[i][q]) p=i-1,q=j;
  31. 31 }
  32. 32 }
  33. 33 int t=1,cnt=0;
  34. 34 for (int j=2;j<=m;j++)
  35. 35 if (f[n][j]>f[n][t]) t=j;
  36. 36 printf("%d\n",f[n][t]);
  37. 37 s[++cnt]=b[t];
  38. 38 int x=n,y=t,xx,yy;
  39. 39 while (f[x][y])
  40. 40 s[++cnt]=b[y],xx=x,yy=y,x=u[xx][yy],y=v[xx][yy];
  41. 41 for (int i=cnt;i>=1;i--) printf("%lld ",s[i]);
  42. 42 return 0;
  43. 43 }

1

2.只存每次加入子序列的b[j],不断一个个递减i找到与b[j]匹配的a[i],得到下一个j的pre[i][j]。

  1. 1 #include<cstdio>
  2. 2 #include<cstdlib>
  3. 3 #include<cstring>
  4. 4 #include<iostream>
  5. 5 using namespace std;
  6. 6
  7. 7 typedef long long LL;
  8. 8 const int N=510;
  9. 9 LL a[N],b[N],s[N];
  10. 10 int f[N][N],pre[N][N];
  11. 11
  12. 12 int main()
  13. 13 {
  14. 14 int n,m;
  15. 15 scanf("%d",&n);
  16. 16 for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
  17. 17 scanf("%d",&m);
  18. 18 for (int i=1;i<=m;i++) scanf("%lld",&b[i]);
  19. 19 memset(f,0,sizeof(f));
  20. 20 memset(pre,0,sizeof(pre));
  21. 21 for (int i=1;i<=n;i++)
  22. 22 {
  23. 23 int p=0;
  24. 24 for (int j=1;j<=m;j++)
  25. 25 {
  26. 26 f[i][j]=f[i-1][j];
  27. 27 if (a[i]==b[j]) f[i][j]=f[i][p]+1,pre[i][j]=p;
  28. 28 else if (a[i]>b[j] && f[i-1][j]>f[i-1][p]) p=j;
  29. 29 }
  30. 30 }
  31. 31 int t=1,cnt=0;
  32. 32 for (int j=2;j<=m;j++)
  33. 33 if (f[n][j]>f[n][t]) t=j;
  34. 34 printf("%d\n",f[n][t]);
  35. 35 int x=n,y=t;
  36. 36 while (f[x][y])
  37. 37 {
  38. 38 while(a[x]!=b[y]&&x) x--;
  39. 39 s[++cnt]=b[y];
  40. 40 y=pre[x][y];
  41. 41 }
  42. 42 for (int i=cnt;i>=1;i--) printf("%lld ",s[i]);
  43. 43 return 0;
  44. 44 }

2

【noi 2.6_2000】&【poj 2127】 最长公共子上升序列 (DP+打印路径)的更多相关文章

  1. POJ 2127 最长公共上升子序列

    动态规划法: #include <iostream> #include <cstdio> #include <fstream> #include <algor ...

  2. poj 2774 最长公共子--弦hash或后缀数组或后缀自己主动机

    http://poj.org/problem?id=2774 我想看看这里的后缀数组:http://blog.csdn.net/u011026968/article/details/22801015 ...

  3. openjudge-NOI 2.6-2000 最长公共子上升序列

    题目链接:http://noi.openjudge.cn/ch0206/2000/ 题解: 裸题,不解释(题目有毒) #include<cstdio> #include<algori ...

  4. CodeForces 10D. LCIS 最长公共上升子序列模板题 + 打印路径

    推荐一篇炒鸡赞的blog. 以下代码中有打印路径. #include <algorithm> #include <iostream> #include <cstring& ...

  5. poj 2774 最长公共子串 后缀数组

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 25752   Accepted: 10 ...

  6. POJ 1458 最长公共子序列(dp)

    POJ 1458 最长公共子序列 题目大意:给出两个字符串,求出这样的一 个最长的公共子序列的长度:子序列 中的每个字符都能在两个原串中找到, 而且每个字符的先后顺序和原串中的 先后顺序一致. Sam ...

  7. 使用后缀数组寻找最长公共子字符串JavaScript版

    后缀数组很久很久以前就出现了,具体的概念读者自行搜索,小菜仅略知一二,不便讨论. 本文通过寻找两个字符串的最长公共子字符串,演示了后缀数组的经典应用. 首先需要说明,小菜实现的这个后缀数组算法,并非标 ...

  8. uva 10066 The Twin Towers (最长公共子)

    uva 10066 The Twin Towers 标题效果:最长公共子. 解题思路:最长公共子. #include<stdio.h> #include<string.h> # ...

  9. 最长公共子序列与最长公共字串 (dp)转载http://blog.csdn.net/u012102306/article/details/53184446

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

随机推荐

  1. Linux SSH , SCP 建立信任关系(免密传输)

    最近有个需求,Jenkins需要将war传输到各个项目节点中,所以需要远程执行各个节点的shell脚本.但是中间有个输入密码的过程,在自动化部署中是行不通的,故需要增加免密登录.具体如下: 如果想在  ...

  2. 一个上传图片,预览图片的小demo

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. vue中选中弹出框内的表格

    一:可多选情况且对应勾选 由于是弹出框形式,所以会出现新增DOM与数据的改变问题,因此要使用$nextTick,不然一开始弹出得时候DOM还没有生成,却要获取DOM会报错:这种多选情况会出现一个bug ...

  4. 【MySQL】MySQL知识图谱

    MySQL 文章目录 MySQL 表 锁 索引 连接管理 事务 日志系统 简单记录 极客时间 - MySQL实战45讲 MySQL知识图谱 表 表 引擎选择 编码问题 表空间管理 字段设计 备份和恢复 ...

  5. C#使用OracleParameter操作数据库

    public static int GetScalar(string sql,params OracleParameter [] OracleParms) { using (OracleConnect ...

  6. oracle 释放表空间到OS(resize)

    1.查看表空间里面的对象 SELECT OWNER AS OWNER, SEGMENT_NAME AS SEGMENT_NAME, SEGMENT_TYPE AS SEGMENT_TYPE, SUM ...

  7. three.js cannon.js物理引擎之约束

    今天郭先生继续说cannon.js,主演内容就是点对点约束和2D坐标转3D坐标.仍然以一个案例为例,场景由一个地面.若干网格组成的约束体和一些拥有初速度的球体组成,如下图.线案例请点击博客原文. 下面 ...

  8. 你这样用过DO循环吗?

    DATA: BEGIN OF text,        word1(4) TYPE c VALUE 'This',        word2(4) TYPE c VALUE 'is',         ...

  9. Linux下载并安装JDK1.8

    https://blog.csdn.net/Future_LL/article/details/84667634

  10. 太极图HTML+CSS(可旋转)代码记录

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...