DP————LIS(最長上升子序列)和LCS(最長公共子序列)問題

LIS問題

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

思路:首先數組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個。spa

這樣當咱們遍歷完整個數組a後就能夠獲得最終的結果。code

時間複雜度分析:O(nlogn)O(nlogn)
C++ 代碼blog

 

#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問題

 挺簡單的,沒什麼好說的,看代碼應該能夠了解。ci

C++ 代碼get

 

#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;
}
相關文章
相關標籤/搜索