• DP————LIS(最长上升子序列)和LCS(最长公共子序列)问题


    LIS问题

    https://www.acwing.com/problem/content/898/

    思路:首先数组a中存输入的数(原本的数),开辟一个数组f用来存结果,最终数组f的长度就是最终的答案;假如数组f现在存了数,当到了数组a的第i个位置时,首先判断a[i] > f[cnt] ? 若是大于则直接将这个数添加到数组f中,即f[++cnt] = a[i];这个操作时显然的。
    当a[i] <= f[cnt] 的时,我们就用a[i]去替代数组f中的第一个大于等于a[i]的数,因为在整个过程中我们维护的数组f 是一个递增的数组,所以我们可以用二分查找在 logn 的时间复杂的的情况下直接找到对应的位置,然后替换,即f[l] = a[i]。

    我们用a[i]去替代f[i]的含义是:以a[i]为最后一个数的严格单调递增序列,这个序列中数的个数为l个。

    这样当我们遍历完整个数组a后就可以得到最终的结果。

    时间复杂度分析:O(nlogn)O(nlogn)
    C++ 代码

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[100001],dp[100001],len;
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        dp[1]=a[1],len=1;
        for(int i=2;i<=n;i++){
            if(dp[len]<a[i]) dp[++len]=a[i];
    
            else{
                int j=lower_bound(dp+1,dp+len+1,a[i])-dp;//lower bound真好用
                dp[j]=a[i];
    
            }
        }
        cout<<len;
        return 0;
    } 

    LCS问题

     挺简单的,没什么好说的,看代码应该可以了解。

    C++ 代码

    #include<bits/stdc++.h>
    using namespace std;
    string a,b;
    int dp[2001][2001];
    int main(){
    
        int len1,len2;
        cin>>len1>>len2>>a>>b;
        for(int j=1;j<=len2;j++)
        for(int i=1;i<=len1;i++){
        if(a[i-1]==b[j-1]) dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
        else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);//阶段划分:已经处理的前缀长度 
        }
        cout<<dp[len1][len2];
        return 0;
    }
  • 相关阅读:
    快速排序
    fedora 配置
    while与do while
    switch选择结构
    if选择结构
    java有参
    java猜拳
    java类的无参方法
    java类与对象
    java数组
  • 原文地址:https://www.cnblogs.com/myhnb/p/11305551.html
Copyright © 2020-2023  润新知