转自:http://blog.csdn.net/joylnwang/article/details/6766317
要求长度为i的序列的Ai{a1,a2,……,ai}最长递增子序列,需要先求出序列Ai-1{a1,a2,……,ai-1}中以各元素(a1,a2,……,ai-1)作为最大元素的最长递增序列,然后把所有这些递增序列与ai比较,如果某个长度为m序列的末尾元素aj(j<i)比ai要小,则将元素ai加入这个递增子序列,得到一个新的长度为m+1的新序列,否则其长度不变,将处理后的所有i个序列的长度进行比较,其中最长的序列就是所求的最长递增子序列。举例说明,对于序列A{35, 36, 39, 3, 15, 27, 6, 42}当处理到第九个元素(27)时,以35, 36, 39, 3, 15, 27, 6为最末元素的最长递增序列分别为
35
35,36
35,36,39
3
3,15
3,15,27
3,6
当新加入第10个元素42时,这些序列变为
35,42
35,36,42
35,36,39,42,
3,42
3,15,42
3,15,27,42
3,6,42
这其中最长的递增序列为(35,36,39,42)和(3,15,27,42),所以序列A的最长递增子序列的长度为4,同时在A中长度为4的递增子序列不止一个。
该算法的思想十分简单,如果要得出Ai序列的最长递增子序列,就需要计算出Ai-1的所有元素作为最大元素的最长递增序列,依次递推Ai-2,Ai-3,……,将此过程倒过来,即可得到递推算法,依次推出A1,A2,……,直到推出Ai为止,
代码如下- unsigned int LISS(const int array[], size_t length, int result[])
- {
- unsigned int i, j, k, max;
- //变长数组参数,C99新特性,用于记录当前各元素作为最大元素的最长递增序列长度
- unsigned int liss[length];
- //前驱元素数组,记录当前以该元素作为最大元素的递增序列中该元素的前驱节点,用于打印序列用
- unsigned int pre[length];
- for(i = 0; i < length; ++i)
- {
- liss[i] = 1;
- pre[i] = i;
- }
- for(i = 1, max = 1, k = 0; i < length; ++i)
- {
- //找到以array[i]为最末元素的最长递增子序列
- for(j = 0; j < i; ++j)
- {
- //如果要求非递减子序列只需将array[j] < array[i]改成<=,
- //如果要求递减子序列只需改为>
- if(array[j] < array[i] && liss[j] + 1> liss[i])
- {
- liss[i] = liss[j] + 1;
- pre[i] = j;
- //得到当前最长递增子序列的长度,以及该子序列的最末元素的位置
- if(max < liss[i])
- {
- max = liss[i];
- k = i;
- }
- }
- }
- }
- //输出序列
- i = max - 1;
- while(pre[k] != k)
- {
- result[i--] = array[k];
- k = pre[k];
- }
- result[i] = array[k];
- return max;
- }