zoukankan      html  css  js  c++  java
  • P1439 【模板】最长公共子序列

    传送门

    思路:经典dp题,可以将第一序列离散化到第二序列,转化为最长上升子序列问题。

    具体为样例  3-1  2-2 1-3 4-4 5-5,则 1 2 3 4 5 转化为 3 2 1 4 5 ,找到这个序列的最长上升子序列即为最长公共序列。

    最长上升子序列 一般两种做法

    1.直接枚举,枚举到第i项时,枚举第i项前的数,当a[j]<a[i],更新dp[i]=max(dp[i],dp[j]+1);算法复杂度o(n^2);

    2.每次以类似贪心的策略使序列的末尾项尽可能小,如此后面的数更容易添加,达到长度最大。

    保证长度为i时,当前的末尾是已知最小的,某一项与末尾相等或者小时,则往前寻找到最适合的位置,更新相应位置的值(可能是末尾)。大于时长度加1,最终长度即为最长公共序列的长度。

    在“使序列的末尾项尽可能小”时,使用了二分搜索,这是复杂度降低的关键,算法复杂度o(nlogn);

    #include<bits/stdc++.h>
    using namespace std;
    int a1[100005];
    int a2[100005];
    int m[100005];
    int a3[100005];
    int main(){
        int n;cin>>n;
        for(int i=0;i<n;i++){
            scanf("%d",&a1[i]);
            m[a1[i]]=i;
        }
        for(int i=0;i<n;i++){
            scanf("%d",&a2[i]);
        }
        int len=1;a3[1]=m[a2[0]];
        for(int i=1;i<n;i++){
            int l=0,r=len;
            if(m[a2[i]]>a3[len])a3[++len]=m[a2[i]];
            else{
                while(l<r){
                    int mid=(l+r)>>1;
                    if(m[a2[i]]<a3[mid])r=mid;
                    else l++;
                }
                a3[l]=min(a3[l],m[a2[i]]);
            }
        }
        cout<<len<<endl;
        return 0;
    }
  • 相关阅读:
    Mimikatz命令简单使用
    WPA加密数据包简单破解-aircrack-ng
    Pwn相关工具安装
    ubuntu火狐浏览器汉化
    Wireshark-sslkeylogfile
    有关RSA 命令总结
    二、volatile关键字
    一、Java JUC简介
    VUE之图表操作
    Drools+springboot
  • 原文地址:https://www.cnblogs.com/mohari/p/13532680.html
Copyright © 2011-2022 走看看