动态规划之最长公共子序列


15.4-2

Q:  不使用数组b完成LCS

A:  直接通过数组c和序列即可。从数组c的最右下角开始,输出的字符按照从右到左的顺序填充公共子序列,即最先输出最后一个字符。步骤如下:

1.  如果当前两个字符不相等则转步骤2,否则输出该字符并且当前位置往左上方前进一位;

2.  查看当前位置的数组c,如果c[i-1][j]>=c[i][j-1]则往上方前进一位,否则往左方前进一位;

 

15.4-3

Q:  书写记忆化(memorized version)的LCS算法

A:  个人理解所谓记忆化,即是从上到下的思路,和人的思维很相似,记录下以前生成的结果,使用递归化的方法将高维问题分解成低维问题,举例来说如果X(m)和Y(n)两个序列最后一个字符相同,则有如下计算方法:

LCS(X(m), Y(n)) = LCS(X(m-1),Y(n-1)) + 1

按照如此想法可以非常简单的写出递归函数,生成数组c

 

15.4-4

Q:  仅需要计算LCS的长度,优化将数组c 的空间,使用2 * min(m,n)空间;可以更进一步的优化,使用min(m,n)空间

A:  2*min(m,n),由于数组c的当前位置取值,仅仅依赖于当前行和上一行,故保存这两行即可;换行时交换这两行的内容即可。

再进一步,当前位置取值,仅仅依赖于其左上位置开始到当前位置之前的所有数值。使用一个类似环形链表的数组存储这些数值,数组中的所有元素组成一个环形链表,数组下标运算不是简单的加法,同时还要取模运算。

 

15.4-5

Q:  给出O(n2)时间复杂度的算法,计算最长递增子序列

A:  两种思路:

1.  将当前序列排序,排序后的序列和原序列进行LCS计算,直接可得到最长递增子序列,排序时间复杂度O(nlogn),LCS时间复杂度O(n2),故此方法总复杂度为O(n2)

 

2.  直接动态规划,从左到右扫描序列X(n),考虑以某元素x(i)结尾的最长递增子序列长度,设其为L(i)可以等到如下公式:

L(i) = max(1,

max(L(j) |(j<i && x(j) < x(i))) + 1)

此公式看起来很复杂,实际上思路很简单,在i之前的某个j,以x(j)结尾的最长递增子序列再加上x(i),一定也是一个递增子序列,遍历所有的j,找到最长的递增子序列即可。

注意还需要使用前驱数组来获得整个子序列,即保存每个元素的前驱元素,这种方法和nlogn 的最长递增子序列方法相同。代码如下:

static int lis_n2(int *p, int len, int *inc_seq)
{
    int max = 1, last = 0;
    int i = 0, j = 0, index = -1;
    int *L = NULL, *prev = NULL;
    
    L = malloc(len * sizeof(int));
    prev = malloc(len * sizeof(int));

    L[0] = 1;
    prev[0] = -1;
    last = 0;
    for (i = 1;i < len;i++) {
        L[i] = 1;
        index = -1;
        for (j = 0;j < i;j++) {
            if (p[j] <= p[i] && L[j] + 1 > L[i]) {
                L[i] = L[j] + 1;
                index = j;
            }
        }
        prev[i] = index;
        if (L[i] > max) {
            max = L[i];
            last = i;
        }
    }

    for (i = max - 1;i >= 0;i--) {
        inc_seq[i] = p[last];
        last = prev[last];
    }

    free(L); free(prev);
    return max;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值