ACM总结——最长公共子序列 & 最长不减(不增)子序列
来源:互联网 发布:如何靠网络挣钱 编辑:程序博客网 时间:2024/04/29 14:28
转自:http://blog.sina.com.cn/s/blog_6a3344990100xyhg.html
ACM总结——最长公共子序列 & 最长不减(不增)子序列
两个经典DP一、最长公共子序列(Longest Common Subsequence:LCS)
设有两个序列A[1...m]和B[1...n],分别对A和B进行划分子序列
A[1] A[1..2] A[1..3] ... A[1..m]
B[1] B[1..2] B[1..3] ... B[1..n]
依次求出A中的每个子序列(从A[1]开始)与B中每个子序列的最长公共子序列,并记录在数组C[m][n]中,C[i][j]表示A[1..i]和B[1..j]的最长公共子序列的长度。
递推公式如下:
①C[i][j]=0 i=0 or j=0
②C[i][j]=C[i-1][j-1]+1 i!=0 and j!=0 and A[i]=B[j]
③C[i][j]=max{C[i-1][j],C[i][j-1]} i!=0 and j!=0 and A[i] != B[j]
路径记录:
记录路径即记录C[i][j]是怎么得来的,从递推公式②③知,C[i][j]的来源有三个:C[i-1][j-1],C[i-1][j],C[i][j-1]。如果是从C[i-1][j-1]得来,那么A[i]=B[j],是最长公共子序列中的一个元素。
可以设置一个数组P[m][n]来记录当前的C[i][j]是怎么得来的,P[m][n]的取值只能有三种,分别记为1 2 3。
构造最长公共子序列:
用递归的方法,检查P[i][j],初始i=m,j=n
如果p[i][j]=1,则记录C[i][j],然后递归处理P[i-1][j-1]
如果P[i][j]=2,不记录,递归处理P[i-1][j]
如果P[i][j]=3,不记录,递推处理P[i][j-1]
直到i=0 or j=0
时间复杂度:O(mn)
二、最长不减(不增)子序列(Longest Order Subsequence)
序列:A[1..n]
方法1:
可以转化为最长公共子序列问题,把序列排序后与原序列找最长公共子序列即可。排序O(nlogn),求最长公共子序列O(n^2),所以时间复杂度为O(n^2)
方法2:
类似上面的方法划分子序列
A[1] A[1..2] A[1..3] ... A[1..n]
依次对每一个序列求最长不减子序列,求后面的会用到前面的结果。用C[1..n]记录求的的长度,即C[i]为A[1..i]最长不减子序列的长度
递推公式:
①C[i]=1 i=1;
②C[i]=max{C[j] | j<i and A[j]<=A[i]}+1 i>1
时间复杂度:
求C[i],需要遍历C[1]...C[i-1],找出最大值(对应的A[j]必须小于等于A[i]),所以时间复杂度为O(n^2)
方法3:
对方法2进行优化,方法2中求C[i]时需要遍历C[1]...C[i-1],这个遍历可以进行优化。
引入一个数组g[n],g[i]表示子序列长度为i时,序列最后一个元素的最小值,初始时,g[n]赋值无穷大,很容易看出,随着子序列长度的增加(即g的下标的增加),序列最后一个元素值必定不会减小(即数组g中的值),所以数组g[n]是单调不减的。
C[i]即等于g[n]中的第一个大于A[i]的元素的下标index,然后用A[i]替换数组g[n]中的这个元素,来更新数组g[n],因为A[i]是序列长度为index的的序列中更小的末元素。
因为g[n]是有序的,所以可以用二分搜索来查找。
这个二分写的很郁闷,怪不得有句话叫做90%程序员写不出无BUG的二分查找程序,这个二分要找出第一个大于某个值的下标,应该把各种情况的二分好好整理一下。
时间复杂度:O(nlogn)
相关题目:
POJ1458
POJ2250
POJ1159
基本的最长公共子序列
POJ2533
最长不减(不增)子序列,用方法1、2即可
WOJ1398
最长不减(不增)子序列,方法1、2超时
题解:http://blog.csdn.net/sinat_19628145/article/details/51161028
0 0
- ACM总结——最长公共子序列 & 最长不减(不增)子序列
- ACM总结——最长公共子序列 & 最长不减(不增)子序列
- 最长公共子序列 & 最长不减(不增)子序列-例题题解【poj1458,poj2250,poj1159】
- ACM-最长公共子序列
- 【ACM】最长公共子序列
- 最长公共子序列总结
- ACM模板——最长公共子序列 LCS
- ACM模板——最长公共上升子序列 LCIS
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列...
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- struts标签不显示
- Java中的Integer、Long等实例的比较
- Java集合框架之Map--Hashtable和Properties源码分析
- hdu 5661
- REST APIs must be hypertext-driven——Posted by Roy T. Fielding
- ACM总结——最长公共子序列 & 最长不减(不增)子序列
- FOJ Common Tangents
- 02.Java 集合 - ArrayList
- WPF 绑定中的TargetNullValue
- hihoCoder 九十二周 数论一·Miller-Rabin质数测试 (数论 筛素数)
- 什么是码率?
- java常见运行时错误
- 矢量数据存入postgis中
- BZOJ 3571: [Hnoi2014]画框