最长递增子序列又叫做最长上升子序列;子序列,正如LCS一样,元素不一定要求连续。本节讨论实现三种常见方法,主要是练手。
题:求一个一维数组arr[i]中的最长递增子序列的长度,如在序列1,-1,2,-3,4,-5,6,-7中,最长递增子序列长度为4,可以是1,2,4,6,也可以是-1,2,4,6。
方法一:DP
像LCS一样,从后向前分析,很容易想到,第i个元素之前的最长递增子序列的长度要么是1(单独成一个序列),要么就是第i-1个元素之前的最长递增子序列加1,可以有状态方程:
LIS[i] = max{1,LIS[k]+1},其中,对于任意的k<=i-1,arr[i] > arr[k],这样arr[i]才能在arr[k]的基础上构成一个新的递增子序列。
#include "iostream"
#include "vector"
#include "ctime"
#include "cstdlib"
using namespace std;
std::vector<int> maxlen;
int lislen;
void LIS(const vector<int> &a){
lislen = 1;
for (int i = 1; i < a.size(); ++i)
{
for (int j = 0; j < i; ++j)
{
if(a[i] > a[j] && maxlen[i] < maxlen[j] + 1){
maxlen[i] = maxlen[j] + 1;
if(maxlen[i] > lislen){
lislen = maxlen[i];
}
}
}
}
}
void printLIS(const vector<int> &a){
std::vector<int> lis;
int index = a.size() - 1;
cout<<lislen<<endl;
while(index >= 0 && lislen > 0){
if(maxlen[index] == lislen){//此时a[index]属于LIS
lis.push_back(a[index]);
lislen--;
}
--index;
}
for (int i = lis.size() - 1; i >= 0; --i)
{
cout<<lis[i]<<"\t";
}
cout<<endl;
}
int main(int argc, char const *argv[])
{
const int N = 10;
std::vector<int> a(N);
maxlen.resize(N,1);//第一次字符的LIS长度为1
srand(time(0));
for (int i = 0; i < N; ++i)
{
int rand_num = rand()%100;
a[i] = rand_num;
cout<<rand_num<<"\t";
}
cout<<endl;
LIS(a);
printLIS(a);
return 0;
}
http://www.ahathinking.com/archives/117.html