AcWing 3510- 最长公共子序列 - 贪心+二分优化

Posted Chivas_/Regal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 3510- 最长公共子序列 - 贪心+二分优化相关的知识,希望对你有一定的参考价值。

LCS问题
题目:
在这里插入图片描述
思路:

LCS是个动态规划问题,但我们可以用DP的思想贪过去

因为a中每个数只出现过一次,所以在这道题里面,我们可以将问题转化为一个LIS问题

首先设置一个数组 i d [ ] id[] id[]用来存入a数组里面的每个出现的数的下标

然后将b数组转化为b’数组,即 b ′ [ i ] = i d [ b [ i ] ] b'[i] = id[b[i]] b[i]=id[b[i]]用来表示:b数组中当前数在a数组中对应的下标

那么要想b中的某个序列在a中也是其中的序列

就需要我们得到的这个b’中的某个子序列,在a中出现过就行了,同时要保证在a中的下标是顺序的

所以问题可以转化为求b’数组的最长上升子序列

具体LIS问题求法可以看 -> 这里

我们发现这个数据范围是 1 e 6 1e6 1e6的,所以我们采用贪心+二分优化,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

代码:

const int N = 1e6 + 10;

int id[N], n;
vector<int> vec;

int main(){
    read(n);
    for(int i = 1, x; i <= n; i ++)  read(x), id[x] = i;
    for(int i = 1, x; i <= n; i ++){ read(x);
        if(!id[x]) continue;//注意:如果没出现过那就不要加进去了
        if(vec.empty() || vec.back() < id[x]) vec.push_back(id[x]);
        else                                  vec[lower_bound(vec.begin(), vec.end(), id[x]) - vec.begin()] = id[x];
    }write(vec.size());
    return 0;
}

以上是关于AcWing 3510- 最长公共子序列 - 贪心+二分优化的主要内容,如果未能解决你的问题,请参考以下文章

AcWing夏季每日一题--最长公共子序列

AcWing 897. 最长公共子序列(LCS朴素版)

解题报告Acwing每日一题 夏季 [1/16]

acwing 272. 最长公共上升子序列

算法基础课题目时间

Jzoj 4889NOIP2016提高A组集训第14场11.12暴力贪心最长公共回文子序列