O(nlogn)实现LCS与LIS

序:
LIS与LCS分别是求一个序列的最长不下降序列序列与两个序列的最长公共子序列
朴素法都可以以O(n^2)实现。
LCS借助LIS实现O(nlogn)的复杂度,而LIS则是通过二分搜索将复杂度从n^2中的朴素查找导致的n降至logn使之整体达到O(nlogn)的复杂度。

具体解析:
http://www.cnblogs.com/waytofall/archive/2012/09/10/2678576.html


LIS代码实现:

/*
About: LIS O(nlogn) 
Auther: kongse_qi
Date:2017/04/26
*/
#include <bits/stdc++.h>
#define maxn 10005
using namespace std;

int n, x[maxn];

void Init()
{
    scanf("%d", &n);
    for(unsigned i = 0; i != n; ++i)
    {
        scanf("%d", &x[i]);
    }
    return ;
}

int lower_find(int cur, int t, int x[])
{
    int l = 0, r = t, mid;
    while(l < r-1)
    {
        mid = (l+r)/2;
        if(x[mid] > cur)    r = mid;
        else l = mid+1;
    }
    return (x[l] >= cur ? l : r);
}

int Lis()
{
    int dp[maxn], top_pos = -1, pos;
    dp[++top_pos] = x[0];
    for(unsigned i = 1; i != n; ++i)
    {
        if(x[i] > dp[top_pos])
        {
            dp[++top_pos] = x[i];
            continue;   
        }
        pos = lower_find(x[i], top_pos, dp);//手写或直接调用STL的lower_bound函数寻找下界
        //pos = lower_bound(dp, dp+top_pos+1, x[i])-dp;
        if(dp[pos] > x[i])  dp[pos] = x[i];
    }
    return top_pos+1;
} 

int main()
{
    freopen("test.in", "r", stdin);

    Init();
    printf("%d\n", Lis());
    return 0;
}

LCS代码实现

/*
About: LCS O(nlogn) 
Auther: kongse_qi
Date:2017/04/26
*/
#include <bits/stdc++.h>
#define maxn 1005
using namespace std;

int n, m, a[maxn], b[maxn];
vector<int> x[maxn];
vector<int> dp;
typedef vector<int>::iterator iterator_t;

void Init()
{
    scanf("%d%d", &n, &m);
    for(unsigned i = 0; i != n; ++i)
    {
        scanf("%d", &a[i]);
    }
    for(unsigned i = 0; i != m; ++i)
    {
        scanf("%d", &b[i]);
    }
    return ;
}

void Pre()
{
    for(unsigned i = m-1; i != -1; --i)
    {
        x[b[i]].push_back(i);
    }
    for(unsigned i = 0; i != n; ++i)
    {
        if(!x[a[i]].empty())
        {
            for(iterator_t j = x[a[i]].begin(); j != x[a[i]].end(); ++j)
            {       
                dp.push_back(*j);
            }
        }
        else dp.push_back(0);
    }
    return ;
}

int Lis()
{
    int qi[maxn], top_pos = -1, pos;
    qi[++top_pos] = dp[0];
    for(iterator_t i = dp.begin()+1; i != dp.end(); ++i)
    {
        if(*i > qi[top_pos])
        {
            qi[++top_pos] = *i;
            continue;   
        }
        pos = lower_bound(qi, qi+top_pos+1, *i)-qi;
        if(qi[pos] > *i)    qi[pos] = *i;
    }
    return top_pos+1;
}

int main()
{
    //freopen("test.in", "r", stdin);

    Init();
    Pre();
    printf("%d\n", Lis()); 
    return 0;
}

自此结束。
箜瑟_qi 2017.04.26 9:01

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值