最长的子序列

时间:2017-01-24 07:41:38

标签: algorithm dynamic-programming bitmask

对于数字N,我们将 LIS数组定义为

以该数字结尾的数字的最长严格增加的子序列。

例如,假设4位数字是1531,那么 LIS数组将是[1,2,2,1]。

在第一个数字结束的最长增长子序列是1(数字1本身),第二个数字是2([1,5]),第三个数字也是2([1,3]),第四个数字是1(数字1本身)。

Problem Statement

这里我使用的是bitmasking算法

for(int i=2;i<=n;i++){
    int x = Lis[i];

    if(x==1){
        for(int j=1;j<(1<<10);j++){
            int last=-1;
            int len=0;
            for(int k=9;k>=0;k--)
                if((j&(1<<k))!=0){ 
                    len++;
                    if(len==1)
                        last=k;
                }

            for(int k=0;k<=last;k++){
                dp[1<<k][i] = (dp[1<<k][i]+ dp[j][i-1])%mod;
            }
        }

        continue;
    }

    for(int j=1;j<(1<<10);j++){
        int last=-1;
        int len=0;
        for(int k=9;k>=0;k--)
            if((j&(1<<k))!=0){ 
                len++;
                if(len==1)
                    last=k;
            }
        if(len+1!=x) continue;

        for(int k=last+1;k<10;k++)
            dp[j|(1<<k)][i] = (dp[j|(1<<k)][i]+ dp[j][i-1])%mod; 
    }
}

但它无法正常工作?任何人都可以解释我处理这个问题的正确方法吗?

1 个答案:

答案 0 :(得分:0)

对于每个数字存储,最长相关序列的长度并按顺序进行:

max_len[]
result

for digit in sequence
    max_len[digit] = max(sub_array(max_len, 1, digit - 1)) + 1
    result.append(max_len[digit])

因为max_len的长度为9或10,具体取决于输入序列中是否允许0,此解决方案在O(n)中运行。 result包含LIS数组。

基本思想是将输入序列中元素e的LIS递归地定义为e之前且小于e的任何元素的LIS。由于我们想要最长的序列,我们显然选择具有最长序列的前任。我们可以将此值记忆为以元素e结尾供以后使用的最长序列,并将e的LIS长度添加到输出序列。