LICS:最长公共上升子序列;

一般令f[i][j]表示a串前i位,b串以j结尾的LICS长度。于是,答案为:max(1~m)(f[n][i]);

朴素做法:O(n^3) 相等时,从1~j-1枚举最大值。

  1. for(int i=;i<=n;i++)
  2. for(int j=;j<=m;j++)
  3. {if(a[i]!=b[j]) f[i][j]=f[i-][j];
  4. else if(a[i]==b[j])
  5. for(int k=;k<j;k++)
  6. if(b[k]<b[j]) f[i][j]=f[i-][k];
  7. }

算法时间复杂度改进思路主要从优化第三层(k)复杂度入手。

升级做法: O(n^2logn) 利用树状数组记录f[i-1][1~j-1]最大值; 数组下表记录的是b串数值。 (第一个j循环预处理,并且更新上一次的成果)需要:树状数组和离散化。

  1. int mx[]
  2. for(int i=;i<=n;i++)
  3. {
  4. for(int j=;j<=m;j++)
  5. {mx[j]=query(b[j]-)//0~b[j]-1 这些数中的f最大值
  6. modify(b[j],f[i-][j])//将上一轮求出的f尝试更新
  7. }
  8. for(int j=;j<=m;j++)
  9. if(a[i]==b[j]) f[i][j]=mx[j]+;
  10. else f[i][j]=f[i-][j];
  11. }

其实这样很麻烦。 复杂度中等,还需要离散化,求具体子序列还要还原。

终极做法:O(n^2) 考虑到,每次进行j循环时,i不动,a[i]的值暂时不变。所以只需边求边记录最大值即可。 直接省掉k层循环。

  1. for(int i=;i<=n;i++)
  2. {
  3. int mx=f[i-][];
  4. for(int j=;j<=m;j++)
  5. if(a[i]!=a[j])
  6. f[i][j]=f[i-][j]
  7. else
  8. f[i][j]=mx+;
  9. if(b[j]<a[i])//j即将变成j+1,尝试更新mx(只有b[j]<a[i]才可以保证上升)
  10. mx=max(mx,f[i-1][j])
  11. }

poj 2127 至于要求具体子序列时,需要记录使之更新的前驱,即path[i][j]=某个位置bj; 因为是“以j结尾”,所以记录bj。输出时输出b[bj];

详见代码: ai,aj记录使答案成为ans的第一个位置。 故可以直接输出b[aj];

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<iostream>
  4. using namespace std;
  5. const int N=;
  6. int f[N][N],path[N][N];
  7. int mj,mx,sum,ai,aj;
  8. int ans[N];
  9. int n,m;
  10. int a[N],b[N];
  11. int main()
  12. {
  13. scanf("%d",&n);
  14. for(int i=;i<=n;i++)
  15. scanf("%d",&a[i]);
  16. scanf("%d",&m);
  17. for(int i=;i<=m;i++)
  18. scanf("%d",&b[i]);
  19. for(int i=;i<=n;i++)
  20. {
  21. mx=;
  22. for(int j=;j<=m;j++)
  23. {
  24. f[i][j]=f[i-][j];
  25. path[i][j]=-;
  26. if(b[j]<a[i]&&f[i-][j]>mx)
  27. {
  28. mx=f[i-][j];
  29. mj=j;
  30. }
  31. else if(a[i]==b[j])
  32. {
  33. f[i][j]=mx+;
  34. path[i][j]=mj;
  35. }
  36. if(sum<f[i][j])
  37. {
  38. sum=f[i][j];
  39. ai=i;
  40. aj=j;
  41. }
  42. }
  43. }
  44. printf("%d\n",sum);
  45. int tmp=sum;
  46. while(tmp)
  47. {
  48. if(path[ai][aj]>-)
  49. {
  50. ans[tmp--]=b[aj];
  51. aj=path[ai][aj];
  52. }
  53. ai--;
  54. }
  55. for(int i=;i<=sum;i++)
  56. printf("%d ",ans[i]);
  57. return ;
  58. }

纯手打。 参考:https://www.cnblogs.com/dream-wind/archive/2012/08/25/2655641.html

LICS O(n*m)+前驱路径的更多相关文章

  1. LeetCode:Word Ladder I II

    其他LeetCode题目欢迎访问:LeetCode结题报告索引 LeetCode:Word Ladder Given two words (start and end), and a dictiona ...

  2. LeetCode:Word Break II(DP)

    题目地址:请戳我 这一题在leetcode前面一道题word break 的基础上用数组保存前驱路径,然后在前驱路径上用DFS可以构造所有解.但是要注意的是动态规划中要去掉前一道题的一些约束条件(具体 ...

  3. [LeetCode] Word Ladder II

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  4. leecode 每日解题思路 64 Minimum Path Sum

    题目描述: 题目链接:64 Minimum Path Sum 问题是要求在一个全为正整数的 m X n 的矩阵中, 取一条从左上为起点, 走到右下为重点的路径, (前进方向只能向左或者向右),求一条所 ...

  5. Cocos2d-x 地图步行实现1:图论Dijkstra算法

    下一节<Cocos2d-x 地图行走的实现2:SPFA算法>: http://blog.csdn.net/stevenkylelee/article/details/38440663 本文 ...

  6. 【Word Ladder II】cpp

    题目: Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) ...

  7. 2018.11.3 PION模拟赛

    期望:100    实际:100 #include<cstdio> #include<cstring> #include<iostream> #include< ...

  8. POJ2127 LICS模板

    题目:http://poj.org/problem?id=2127 十分费劲地终于记录好了路径……用一个前驱. 这是 n^2 的LICS方法.其实就是 n ^ 2 log n 把“找之前的d [ j ...

  9. HDU 4862 Jump(最小K路径覆盖)

    输入一个n×m网格图,每个结点的值为0-9,可以从任意点出发不超过k次,走完每个点且仅访问每个结点一次,问最终的能量最大值.不可全部走完的情况输出-1. 初始能量为0. 而结点(x,y)可以跳跃到结点 ...

随机推荐

  1. 过渡与动画 - 缓动效果&基于贝塞尔曲线的调速函数

    难题 给过渡和动画加上缓动效果是一种常见的手法(比如具有回弹效果的过渡过程)是一种流行的表现手法,可以让界面显得更加生动和真实:在现实世界中,物体A点到B点往往也是不完全匀速的 以纯技术的角度来看,回 ...

  2. ubuntu16.04在GTX1070环境下安装 cuda9.1

    设备要求 系统:Ubuntu16.04 显卡:GTX 1070 驱动:nvidia系列,显卡驱动的版本必须大于等于cuda的sh文件名里面的版本号 驱动可从 此处 下载,我已经整理好了 检查安装驱动 ...

  3. PHP 文件写入和读取(必看篇)

    文章提纲: 一.实现文件读取和写入的基本思路 二.使用fopen方法打开文件 三.文件读取和文件写入操作 四.使用fclose方法关闭文件 五.文件指针的移动 六.Windows和UNIX下的回车和换 ...

  4. 剑指offer:二叉树中和为某一值的路径

    本来这只是一个普通的算法题,但是当初自己OJ上提交时,总是提交失败,而我自己认定程序逻辑没有任何问题.然后开始就在本机上调试,结果发现这是由于Python的对象机制而引发的.所以先把问题算法题贴出来, ...

  5. python 中的列表(list)

    一.生成一个列表 直接生成 L1 = [1, 2, 3, 4, 5] 列表解析式 >>> L2 = [x for x in range(1, 10, 2)] #从1到10的迭代,步长 ...

  6. HDU 2052 Picture

    http://acm.hdu.edu.cn/showproblem.php?pid=2052 Problem Description Give you the width and height of ...

  7. What is the difference between apache tomcat deployer and core version? - Stack Overflow

    java - What is the difference between apache tomcat deployer and core version? - Stack Overflowhttps ...

  8. activiti engine.schema.update DB_SCHEMA_UPDATE_FALSE

    engine.properties # engine propertiesengine.schema.update=trueengine.activate.jobexecutor=falseengin ...

  9. Activiti中子流程:SubProcess,CallActiviti的区别

    子流程:SubProcess,CallActiviti的区别 https://community.alfresco.com/thread/221771-call-activiti-vs-subproc ...

  10. Jfrog Artifactory 创建docker 镜像仓库以及 push 镜像到 该仓库.

    1. 安装aitifactory 以及 启动 使用30天有效期激活 不在阐述. 2. 登录artifactory username:admin password:password 3. 创建 仓库 在 ...