首先,要理解下子串子序列的含义:

子串:来源于原序列连续的一段。

子序列:来源于原序列中元素相对顺序不变的一段,不要求元素连续。

LCS(最长公共子序列)

给定两个序列A、B,设C[i, j]=LCS(Ai, Bj),其中Ai、Bj分别表示A从首元素到第i个元素的一段、B从首元素到第j个元素的一段, ai、bi分别表示A中第i个元素、B中第j个元素。则LCS的状态转移方程为:

C[i, j] = 0. ( if i == 0 or j == 0 )

C[i, j] = C[i-1, j-1] + 1. ( if i,j > 0 and ai == bi )

C[i, j] = max(C[i-1, j], C[i, j-1]). ( if i,j > 0 and ai != bi )

根据该递归方程可知,这是一个dp思想,实现就是构造出数组C。具体步骤如下:

先构造出第一行和第一列。

C[0, 0]

...

C[0, j]

...

C[0, n]

...

C[i, 0]

...

C[n, 0]

再依次构造出其余各行。

C[0, 0]

...

C[0, j]

...

C[0, n]

...

...

...

...

...

C[i, 0]

...

C[i, j]

...

C[i, n]

...

...

...

...

...

C[n, 0]

...

C[n, j]

...

C[n, n]

该算法复杂度为O(n^2).

LIS(最长递增子序列)

这里考虑严格递增(不严格递增类似)。给定一个序列A,设ai表示A中的第i个元素,I[i]为从首元素到以ai结尾的序列的LIS,则其状态转移方程为:

I[i] = 0. ( if i == 0 )

I[i] = I[i-1]. ( if ai <= ai-1)

I[i] = max( I[i], I[i-1] + 1). ( if ai > ai-1 )

若只是要求求出LIS的长度,则可用一个栈来储存LIS,并结合二分来维护LIS,该栈的最后一个元素为最长LIS的尾元素,栈长即为LIS,算法复杂度为O(n*logn)。若要求输出LIS,则可以考虑求A和sort(A)的LCS,此LCS即为A的最长不减子序列,进一步得到LIS只需剔除那些多余相等的元素,算法复杂度为O(n^2)。

LCIS(最长递增公共子序列)

此问题可以看成是LIS问题和LCS问题的重叠。给定两个序列A、B,设CI[i][j]为A中前i个元素,B中前j个元素且以B[j]结尾的LCIS, 则其状态转移方程为:

CI[i][j] = CI[i-1][j]. ( if A[i] != B[j] )

CI[i][j] = max(CI[i-1][k]) + 1. ( if A[i] == B[j] ) , 1 <= k <= j - 1 && B[k] < A[i] .

由此状态转移方程,可以写出最小O(n^2)的算法。同样用二维数组(或一维数组,具体原因参造下面“有关空间复杂度的降低”)。

如何理解上述状态转移方程:对于第一个等式,如果A[i] != B[j],而CI[i][j]是以B[j]为结尾的LCIS,则必有CI[i][j] = CI[i-1][j]。对于第二个等式,如果A[i] == B[j],则CI[i][j] 应该为CI[i-1][1] ~ CI[i-1][j-1]中LCIS最长且满足B[k] < A[i](满足递增条件),即A[i]应该接到B[1] ~ B[j-1]中小于其本身且LCIS最长的B[k]的右边。在寻找max(CI[i-1][k])的时候,其实可以在求CI[i-1][j-1]时求出,即每次计算CI[i][j]的时候,同时计算出max(CI[i][k])。这样可以将复杂度降为O(n^2)。具体实现步骤如下:

初始化max = 0,内层循环 j = 1 ~ m。

if (A[i] > [B[j] && max < CI[i-1][j]),max = CI[i-1][j]。

这样,当循环到A[i] == B[j] 时,max即为max(CI[i-1][k])。为什么是A[i] > B[j]呢,因为这个时候A[i]为考虑中的公共元素,当它大于B[j]时,说明B[j]后面可能有和它相等的数,故A[i]可能接到B[j]的后面。若是A[i] < B[j],则A[i]不可能接到B[j]的后面(因为递增子序列)。

这个问题如果允许复杂度再大一点话,其实是可以转化为三个序列求LCS的问题,这三个序列分别是A,B, sort(A) (或sort(B))。若A中有重复元素,则需剔除sort(A)中的重复元素,再求三者的LCS(利用三维或者二维数组实现,可降一维原因情参造“有关空间复杂度的降低”)。可以给出具体证明:

设序列A={a0, a1, ... as},B={b0, b1, ... bt},且LCS(A, B) = {c0, c1, ... cm}, S = {s0, s1, ... sm} (其中si = LCS(ci, sort(ci))。

则LCIS(A, B) = max(si)(其中i = 0, 1, ... m)。

因为sort(ci) 包含于sort(A), 故sort(A) = {a0', a1', ... sort(ci), ... as'},且sort(ci)前面的元素均不大于sort(ci)中最小的元素,sort(ci)后面的元素均不小于sort(ci)中最大的元素,且|ci| = |sort(ci)|,故si = LCS(ci, sort(ci)) = LCS(ci, sort(A))。

故LCIS(A, B) = max(LCS(ci, sort(A)) = max(LCS(LCS(A, B), sort(A))) = LCS(A, B, sort(A))。

有关空间复杂度的降低

对于上面三种问题,若采用了数组来实现状态转移,且是逐行(或逐列)扫描,则可降低一维,因为上面三种问题的状态转移数组的每一位的求解时均只是利用到该位的左上及其正上和正左的元素,而且最终的答案在最后的那一行(或列)中,故可以减去一维,实现逐行(或逐列)重复扫描,从而降低了空间复杂度。

lis算法c语言,LCS、LIS、LICS算法相关推荐

  1. 最近最久未使用页面置换算法C语言,LRU页面置换算法模拟-最近最久未使用置换算法...

    LRU页面置换算法模拟-最近最久未使用置换算法 LRU页面置换算法模拟-最近最久未使用置换算法|课程设计|计算机数据库课程设计 一.设计目的 1.用C语言实现最近最久未使用(LRU)置换算法. 2.了 ...

  2. java实现随机数生成算法_Java 语言实现的随机数生成算法

    广州疯狂软件学院拥有三大课程体系包括:java课程,android课程,ios课程,疯狂软件年终钜惠,报名java就业班,免费赠送基础班,名额有限,本月火热报名中,欢迎有志之士电话或者QQ咨询. [导 ...

  3. bwt比对算法 C语言,DNA比对算法:BWT

    DNA比对算法:BWT BWT算法,实质上是前缀树的一种实现.那么什么是前缀树呢? 一.前缀树 对于问题p in S?如果S=rpq,那么p为S前缀rp的一个后缀. 于是,为了判断p in S 是否成 ...

  4. 妙趣横生的算法(c语言实现),妙趣横生的算法(C++语言实现) 带目录完整pdf[4MB]

    <妙趣横生的算法(C++语言实现)>内容丰富,生动有趣,寓教于乐,旨在帮助读者学习数据结构和算法的相关知识,从而开阔眼界,培养编程兴趣,提高编程能力,增强求职的竞争力.如果您想提高自己对算 ...

  5. c语言程序设计 算法,C语言程序设计第二章算法

    <C语言程序设计第二章算法>由会员分享,可在线阅读,更多相关<C语言程序设计第二章算法(38页珍藏版)>请在人人文库网上搜索. 1.C程序设计,主讲人:袁丽,燕大里仁基础教学部 ...

  6. 短进程算法c语言,短进程优先算法C语言实现

    短进程优先算法C语言实现 1.本实验实现了短进程优先的进程调度操作,但因为是非抢占式,所以实现起来比较简单. 短进程优先算法是以作业的长短来计算优先级,作业越短,其优先级越高.作业的长短是以作业所要求 ...

  7. 用c语言编写插入排序算法,C语言实现常用排序算法——插入排序

    插入排序是最基础的排序算法,原理: 首先1个元素肯定是有序的,所以插入排序从第二个元素开始遍历: 内循环首先请求一个空间保存待插入元素,从当前元素向数组起始位置反向遍历: 当发现有大于待插入元素的元素 ...

  8. 数据拟合算法c语言实现,数据拟合算法剖析及C语言实现.doc

    数据拟合算法剖析及C语言实现 数据拟合算法剖析及C语言实现 [摘要]数据拟合在很多地方都有应用,主要用来处理实验或观测的原始离散数据.通过拟合可以更好的分析和解释数据.在引用前人的算法基础上,采用正交 ...

  9. 人工免疫算法c语言程序,基于人工免疫算法的模拟电路故障诊断

    摘要: 模拟电路故障诊断一直以来都是十分必要和有意义的,目前已成为热门的研究课题.现代电子技术和计算机技术的迅速发展促进了片上系统和混合集成电路的大量涌现,这也对模拟电路的测试和故障诊断提出了更高的要 ...

  10. JAVA梅森旋转随机算法,C语言实现梅森旋转算法

    原理: 梅森旋转算法是一种伪随机数生成算法 1.定义相关宏和结构体 #include #include #include #include typedef unsigned int uint; #de ...

最新文章

  1. Fatal error:SQL Server 不存在或拒绝访问。
  2. python速成一小时_Python学习|一小时快速入门python(一)
  3. 南开大学滨海学院计算机科学系,【公示】南开大学滨海学院2019届“优秀毕业生”、“十佳毕业生” 评选结果公示...
  4. tableMerge 表格列自动合并
  5. 七月算法机器学习 9 推荐系统与应用
  6. 用《只狼》教你学会Git(中)
  7. sparksql处理mysql_Spark记录-SparkSQL远程操作MySQL和ORACLE
  8. 主板aspm关闭_【装机加人品】主板如何开启与关闭超线程技术?
  9. 树莓派-MLX90614
  10. day 69-70 一对一 一对多 多对一联表查询
  11. Python数据爬虫学习笔记(11)爬取千图网图片数据
  12. 移动硬盘坏了,自己搞定解决方案
  13. zebra扫码枪复位_zebra斑马条码打印机常见问题和解决办法
  14. 计算机毕业设计SSM 家乡旅游文化推广网站【附源码数据库】
  15. Xtreme9.0 - Mr. Pippo's Pizza 数学
  16. Python量化交易实战-05什么是股票?
  17. 牌照发布后的第20天,上海MWC,中国5G,GO!
  18. C# 集合-并发处理
  19. 找回sonarqube管理员密码
  20. 用 PaddleOCR 进行集装箱箱号检测识别详细教程

热门文章

  1. EPLAN使用技巧总结
  2. Flutter | bloc 之 state 使用优化
  3. 每日1500元只为陪伴,正值妙龄的90、95后正在被“孤独”侵袭
  4. 【2019.07.10】python + OpenCV + adb 实现 自动 微信跳一跳
  5. 女朋友问小灰:什么是数据仓库?什么是数据湖?什么是智能湖仓?
  6. Linux Shell 脚本之循环语句
  7. linux如何kill僵尸进程,linux 如何杀死僵尸进程——原理及操作
  8. Halium 9 尝鲜 -- 在小米平板4上的移植 (七)
  9. php handle 用用法,PHP_关于php fread()使用技巧,说明 string fread ( int handle, int le - phpStudy...
  10. 拉丁方阵(内置问题,渴望求解!)