longest increasing subsequence (最长递增子序列)
来源:互联网 发布:淘宝有找兼职的吗 编辑:程序博客网 时间:2024/05/16 06:27
转自algorithmist 原文链接 http://www.algorithmist.com/index.php/Longest_Increasing_Subsequence
The Longest Increasing Subsequence problem is to find the longest increasing subsequence of a given sequence. It also reduces to aGraph Theory problem of finding the longest path in aDirected acyclic graph.
Overview
Formally, the problem is as follows:
Given a sequence , find the largest subset such that for everyi <j,ai < aj.
Techniques
Longest Common Subsequence
A simple way of finding the longest increasing subsequence is to use theLongest Common Subsequence (Dynamic Programming) algorithm.
1. Make a sorted copy of the sequenceA, denoted asB.O(nlog(n)) time.
2. Use Longest Common Subsequence on with A andB. O(n2) time.
Dynamic Programming
There is a straight-forward Dynamic Programming solution in O(n2) time. Though this is asymptotically equivalent to theLongest Common Subsequence version of the solution, the constant is lower, as there is less overhead.
Let A be our sequence . Define qk as the length of the longest increasing subsequence of A, subject to the constraint that the subsequence must end on the elementak. The longest increasing subsequence of A must end on some element of A, so that we can find its length by searching for the maximum value of q. All that remains is to find out the valuesqk.
But qk can be found recursively, as follows: consider the setSk of alli < k such that ai <ak. If this set is null, then all of the elements that come before ak are greater than it, which forcesqk = 1. Otherwise, ifSk is not null, then q has some distribution overSk. By the general contract of q, if we maximize q overSk, we get the length of the longest increasing subsequence inSk; we can appendak to this sequence, to get that:
If the actual subsequence is desired, it can be found in O(n) further steps by moving backward through the q-array, or else by implementing the q-array as a set of stacks, so that the above "+ 1" is accomplished by "pushing"ak into a copy of the maximum-length stack seen so far.
Some pseudo-code for finding the length of the longest increasing subsequence:
function lis_length( a ) n := a.length q := new Array(n) for k from 0 to n: max := 0; for j from 0 to k, if a[k] > a[j]: if q[j] > max, then set max = q[j]. q[k] := max + 1; max := 0 for i from 0 to n: if q[i] > max, then set max = q[i]. return max;
Faster Algorithm
There's also an O(nlogn) solution based on some observations. LetAi,j be the smallest possible tail out of all increasing subsequences of lengthj using elements .
Observe that, for any particular i, . This suggests that if we want the longest subsequence that ends withai + 1, we only need to look for a j such thatAi,j < ai + 1 < =Ai,j + 1 and the length will bej + 1.
Notice that in this case, Ai + 1,j + 1 will be equal toai + 1, and allAi + 1,k will be equal toAi,k for .
Furthermore, there is at most one difference between the set Ai and the set Ai + 1, which is caused by this search.
Since A is always ordered in increasing order, and the operation does not change this ordering, we can do abinary search for every single .
Further explain:--GONG Zhi Tao 11:19, 1 August 2012 (EDT)
We have elements: .
And we have a longest increasing subsequences of them: , for any Ai,k(1 < = k < = j) you could not find a smaller alternative.
Now we have a new element: ai + 1
What we can do about it:
1. insert it at the back if Ai,j <ai + 1, where we will have a longer one;
2. make it an alternative for Ai,k if
Alternative means that we MIGHT get longer ones if using the new element.
C++ implementation
#include <vector>using namespace std; /* Finds longest strictly increasing subsequence. O(n log k) algorithm. */void find_lis(vector<int> &a, vector<int> &b){vector<int> p(a.size());int u, v; if (a.empty()) return; b.push_back(0); for (size_t i = 1; i < a.size(); i++) { // If next element a[i] is greater than last element of current longest subsequence a[b.back()], just push it at back of "b" and continueif (a[b.back()] < a[i]) {p[i] = b.back();b.push_back(i);continue;} // Binary search to find the smallest element referenced by b which is just bigger than a[i] // Note : Binary search is performed on b (and not a). Size of b is always <=k and hence contributes O(log k) to complexity. for (u = 0, v = b.size()-1; u < v;) {int c = (u + v) / 2;if (a[b[c]] < a[i]) u=c+1; else v=c;} // Update b if new value is smaller then previously referenced value if (a[i] < a[b[u]]) {if (u > 0) p[i] = b[u-1];b[u] = i;}} for (u = b.size(), v = b.back(); u--; v = p[v]) b[u] = v;} /* Example of usage: */#include <cstdio>int main(){int a[] = { 1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 };vector<int> seq(a, a+sizeof(a)/sizeof(a[0])); // seq : Input Vectorvector<int> lis; // lis : Vector containing indexes of longest subsequence find_lis(seq, lis); //Printing actual output for (size_t i = 0; i < lis.size(); i++)printf("%d ", seq[lis[i]]); printf("\n"); return 0;}
- 最长递增子序列 (Longest Increasing Subsequence)
- 最长递增子序列 (Longest Increasing Subsequence)
- 最长递增子序列 (Longest Increasing Subsequence)
- 最长递增子序列 (Longest Increasing Subsequence)
- Longest increasing subsequence,最长递增子序列
- 最长递增子序列 (Longest Increasing Subsequence)
- 最长递增子序列-Longest Increasing Subsequence
- 最长递增子序列 (Longest Increasing Subsequence)
- Longest Increasing Subsequence 最长递增子序列
- 最长递增子序列详解(longest increasing subsequence)
- 最长递增子序列详解(longest increasing subsequence)
- 最长递增子序列详解(longest increasing subsequence)
- longest increasing subsequence (最长递增子序列)
- [动态规划] 最长递增子序列 (Longest Increasing Subsequence)
- 最长递增子序列详解(longest increasing subsequence)
- 最长递增子序列详解(longest increasing subsequence)
- 最长递增子序列 Longest Increasing Subsequence (LIS)
- 最长递增子序列(longest increasing subsequence)
- 旋转交换或向量旋转
- 曾国藩是如何“脱胎换骨”的
- 那些年困扰我们的乘法口诀
- 当xml里面有命名空间的时候去读问题
- Android报错及快速解决方法
- longest increasing subsequence (最长递增子序列)
- GitHub IP地址变更
- (李嘉诚)教五年内买车买房——理财篇
- php输出方法---小结 echo print var_dump Print_r
- 在Fedora Core 18上配置Apache 2
- Apache 搭建虚拟主机
- hdu 1025 Constructing Roads In JGShining's Kingdom(LIS)题意较难转换成LIS
- 解决MVC3 服务器无法在已发送 HTTP 标头之后设置状态 问题
- 数据库查询集与反射的应用(自己写的小例子)