密码脱落-蓝桥杯-最大公共子序列

https://www.acwing.com/problem/content/description/1224/

最长公共子序列问题在《算法导论》P222页有其原理证明。

“比对两段DNA序列的相似度”就是一个很好的例子。

动态规划的核心思想就是自底向上地解决递归中的重复子结构问题。利用空间迭代(或者说是状态转移)来换取递归的堆栈操作和时间。

纯dfs解法1:33分,但其实应该是错的,最小解应该取两个dfs的min

#include<bits/stdc++.h>
using namespace std;

string s;
int ans;
void dfs(int i,int j,int u){
    if(i>=j)    {
        ans=u;
        return ;
    }
    if(s[i]!=s[j]){
        dfs(i+1,j,u+1);
        dfs(i,j-1,u+1);
    }else{
        dfs(i+1,j-1,u);
    }
    
    return ;
}
int main(){
    cin>>s;
    int n=s.size();
    dfs(0,n-1,0);
    cout<<ans;
    return 0;
}

纯dfs解法2:正确写法:

此题无法继续剪枝;

#include<stdc++.h>
using namespace std;

string s;
int ans;
int  dfs(int i,int j,int u){
    if(i>=j)    {
        return u;
    }
    if(s[i]!=s[j]){
        return min(dfs(i+1,j,u+1),dfs(i,j-1,u+1));
    }else{
        return dfs(i+1,j-1,u);
    }
}
int main(){
    cin>>s;
    int n=s.size();
    cout<<dfs(0,n-1,0);
    
    return 0;
}

3.dp区间规划:

为了方便理解我还是单独开辟空间给逆序串来比对

优雅而快捷~

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
string s;
int dp[N][N];

int main(){
    cin>>s;
    int n=s.size();
    string s2=s;
    reverse(s2.begin(),s2.end()); //单独开辟空间给逆序串来比对
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(s[i]==s2[j])  dp[i][j]=dp[i-1][j-1]+1;
            else    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
    }
    cout<<n-dp[n][n];
   
    return 0;
}
posted @ 2022-02-10 22:02  秋月桐  阅读(40)  评论(0编辑  收藏  举报