洛谷 P2758 编辑距离 题解(dp)

题目链接

题目思路

本来我以为这个题目是和最长子序列有关,用max(da,db)-最长子序列的长度,但是我果然太菜了

随便一组数据就足以证明这个思路是错的

如 rcpw wbl 答案应该是4,而我的答案是3

进入正题

设两个字符串A,B 用一个二维数组f存储状态 一维存A串 一维存B串 一共有如下四种操作:

删:可以看做把A串最后一个字符删去后不再考虑这个字符 所以f(i,j)=min(f(i,j),f(i-1,j)+1);

加:可以看做与B串最后一个字符抵消后不再考虑这个字符 所以f(i,j)=min(f(i,j),f(i,j-1)+1);

改:可以看做删和加的集合 抵消了A、B串最后的两个字符 所以f(i,j)=min(f(i,j),f(i-1,j-1)+1);

当然若A、B串最后一个字符相同就可以不用操作了

此外注意输入时scanf(“%s”,a+1) 那么长度的测量就要strlen(a+1)

最后注意边界的处理

代码

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
const int maxn=2e3+5;
int da,db,dp[maxn][maxn];
char a[maxn],b[maxn];
int main(){
    scanf("%s %s",a+1,b+1);
    da=strlen(a+1);
    db=strlen(b+1);
    for(int i=0;i<=da;i++){//边界处理
        dp[i][0]=i;
    }
    for(int j=0;j<=db;j++){
        dp[0][j]=j;
    }
    for(int i=1;i<=da;i++){
        for(int j=1;j<=db;j++){
            int k=1;
            if(a[i]==b[j]){
                k=0;
            }
            dp[i][j]=min(min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+k);
        }
    }
    printf("%d\n",dp[da][db]);
    return 0;
}

发布了68 篇原创文章 · 获赞 2 · 访问量 2264

猜你喜欢

转载自blog.csdn.net/m0_46209312/article/details/104940471