• P1439 【模板】最长公共子序列


    题目描述

    给出1-n的两个排列P1和P2,求它们的最长公共子序列。

    输入输出格式

    输入格式:

    第一行是一个数n,

    接下来两行,每行为n个数,为自然数1-n的一个排列。

    输出格式:

    一个数,即最长公共子序列的长度

    输入输出样例

    输入样例#1: 
    5 
    3 2 1 4 5
    1 2 3 4 5
    
    输出样例#1: 
    3

    说明

    【数据规模】

    对于50%的数据,n≤1000

    对于100%的数据,n≤100000

    /*
    关于LCS长度等于构造出来的新序列的LIS长度的证明: 
    
    (1) A、B的一个公共子序列对应新序列的一个严格递增子序列
    证: 
        假设A、B的某一个公共子序列长度为k,则其公共子序列在A和B中可以写为
        {A1,A2, ..., Ak}
        {B1,B2, ..., Bk}
        
        如此有A1 = B1,A2 = B2, ...., Ak = Bk, 考虑元素Bi在B中的序号P(Bi),则有
        P(B1)< P(B2) < ... < P(Bk)
        注意此严格递增子序列属于新序列的一个子序列,因此得证
     
    (2) 新序列的一个严格递增子序列对应A、B的一个公共子序列
    证: 
        设新序列的一个严格递增子序列{P1,P2, ..., Pk},
        任意两个相邻的P不可能属于A中同一个元素,因为A中某元素在B中的序号按照降序排列,且P为上升序列。 
        所以每个P均对应于A中不同位置的元素,设为{A1, A2, ..., Ak}。
        且每个P也对应B中唯一的一个元素,假设为{B1,B2, ..., Bk},
        由P的定义可知A1= B1, A2 = B2, ...., Ak = Bk,因此得证。
    
    步骤:
    (1) 计算A中每个元素在B中的序号,并构成新序列
    (2) 使用LIS的方法计算最长严格递增子序列
    (3) 获取最长公共子序列
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    const int N=100005;
    
    int n;
    int a[N],b;
    int seq[N],seq_len;
    int lis[N],lis_len;
    vector<int> vec[N];
    
    int read()
    {
        char c=getchar();int num=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
            num=num*10+c-'0';
        return num;
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;++i)
            a[i]=read();
        for(int i=1;i<=n;++i)
        {
            vec[b=read()].push_back(i);
        }
        for(int i=1;i<=n;++i)
            for(int j=vec[a[i]].size()-1;j>=0;--j)
                seq[++seq_len]=vec[a[i]][j];
        lis[++lis_len]=seq[1];
        for(int i=2;i<=seq_len;++i)
        {
            if(seq[i]>lis[lis_len])
                lis[++lis_len]=seq[i];
            else
                lis[lower_bound(lis+1,lis+lis_len+1,seq[i])-lis]=seq[i];
        }
        printf("%d",lis_len);
        return 0;
    }
  • 相关阅读:
    Android内存分析和调优(中)
    Android内存分析和调优(上)
    背包九讲之四:混合背包问题:01,完全,多重的混合
    背包九讲之三:多重背包问题:一个物品允许选有限次
    背包九讲之二:完全背包问题:一个物品允许选多次
    背包九讲之一:01背包问题:一个物品只允许选一次
    动态规划:最长递增子序列
    动态规划:采油区域
    Hankson的趣味题
    动态规划:传纸条
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8444440.html
Copyright © 2020-2023  润新知