最长不下降子序列&最长公共子序列的O(n^2)以及O(n log n)解法

本文介绍了如何使用二分查找优化最长不下降子序列问题,从O(n^2)改进到O(n log n)。同时,探讨了最长公共子序列的O(n^2)解法,并提出了通过转换排列问题利用最长不下降子序列算法解决特殊情况的思路。
摘要由CSDN通过智能技术生成

2018.7.13 Chengdu

学了一天的 DP D P 问题,啥都没听懂,但是勉强听懂了最长不下降子序列的求法(我太弱啦),特发于此。


二分查找的妙(误)用·最长不下降子序列

最长不下降子序列作为DP的简单线性问题之一,其最常见的解法是 O(n2) O ( n 2 ) 的暴力枚举。用数组 a(i) a ( i ) 表示该序列中的第 i i 项,用数组 f(i) f ( i ) 表示序列的前 i i 项的最长不下降子序列长度,并初始化 f(1)=1 f ( 1 ) = 1 。假设当前已经求出 [1,i) [ 1 , i ) 范围内的 f f 数组的值,接下来求 f(i) f ( i ) ,只需要扫描 [1,i) [ 1 , i ) 中每一个元素 j j ,如果有 a(j)a(i) a ( j ) ≤ a ( i ) ,那么 f(i)=max{ f(i),f(j+1)} f ( i ) = m a x { f ( i ) , f ( j + 1 ) }

所以可以很容易得到其 O(n2) O ( n 2 ) 代码:

#include<bits/stdc++.h>
using namespace std;
int n,x,a[1100000],f[1100000],ans;
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        f[i]=1;
        for(int j=0;j<n;j++)
            if(a[j]<=a[i]) f[i]=max(f[i],f[j]+1);
        ans=max(ans,f[i]);
    }
    printf("%d\n",ans);
    return 0;
}

那么我们如何使用二分查找来优化算法达到 O(nlogn) O ( n log ⁡ n ) 呢?

先定义一个数组 f(i) f ( i ) ,初始化全为 + + ∞

这样的话怎么去更新数组呢?我们来拿一个序列做例子。这个序列的长度为 9 9 ,序列表示为: ( 3 , 5 , 1 , 2 , 4 , 7 , 6 , 8 , 9 )

i i 1 2 2 3 4 4 5 6 6 7 8 8
f(i) f ( i ) + + ∞ + + ∞ + + ∞ + + ∞ + + ∞ + + ∞ + + ∞ + + ∞

首先输入 3 3 ,按照升序插入数组 f 中。此时的 f f 中的值均为 + ,故 3 3 最小,插入到 f ( 1 )

i i 1 2 2 3 4 4 5 6 6 7 8 8
f(i) f ( i ) 3 3 + + + ∞ + + ∞ + + ∞ + + ∞ + + ∞ + + ∞

接下来插入 5 5 5 3 3 要大,但显然比 + 要小,所以把它插入到 f(2) f ( 2 )

i i 1 2 2 3 4 4 5 6<
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值