题解:编辑距离

题目

题目描述

设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:
1、删除一个字符;
2、插入一个字符;
3、将一个字符改为另一个字符;
!皆为小写字母!

输入格式

第一行为字符串A;第二行为字符串B;字符串A和B的长度均小于2000。

输出格式

只有一个正整数,为最少字符操作次数。

输入输出样例

输入
sfdqxbw
gfdgw
输出
4

解析

正解

这道题其实是一个分情况讨论的动态规划
我们定义状态:dp[i][j]表示两个字符串,a到i处,b到j处时操作的最少次数
所以我们的状态转移方程如下:
1、当a[i][j] == b[i][j] 时,即a的第i位和b的第j位相同,此时我们是不需要进行修改的,直接从上一位转移过来即可
2、dp[i][j] = min(dp[i - 1][j - 1] + 1,dp[i][j - 1] + 1,dp[i - 1][j] + 1);
其中,dp[i - 1][j - 1] + 1 表示把字符改掉,dp[i - 1][j] + 1表示删掉a,dp[i][j - 1] + 1表示删掉b

注意事项

别忘了初始化!
不初始化会出人命的。。。。。。

for(int i = 1;i <= max(n,m); i++) {
		    dp[i][0] = i;
		    dp[0][i] = i;
}

初始化代码的含义是什么呢?
想要达到dp[i][0],你需要增加i个字符,也就是操作i次,dp[0][i]同理。千万不要忽视了这个初始化的作用,这个初始化在接下来的转移中会被用到好几次,不写初始化会得0分。。。
再次吐槽一下样例是真的无比的水,我从两个网站搞了题,不写初始化两个网站的样例都过了,然而全WA了。。。千万不要相信样例,写之前除了转移方程,其余的细节也要想周全,一定要自己造一些样例,不然错了自己都不知道。。。。。。

代码

#include<bits/stdc++.h>
#define min(a,b,c) min(a,min(b,c))
using namespace std;
int n,m;
char a[2001],b[2001];
int dp[2001][2001];
int main() {
    memset(dp,0,sizeof(dp));
    scanf(" %s" ,a + 1);
    scanf(" %s" ,b + 1);
    n = strlen(a + 1);
    m = strlen(b + 1);
    dp[0][0] = 0;
    for(int i = 1; i <= max(n,m); i++) {
	    dp[i][0] = i;
	    dp[0][i] = i;
    }
    for(int i = 1; i <= n; i++) {
	    for(int j = 1; j <= m; j++) {
		    if(a[i] == b[j]) dp[i][j] = dp[i - 1][j - 1];
		    else dp[i][j] = min(dp[i - 1][j - 1] + 1,dp[i][j - 1] + 1,dp[i - 1][j] + 1);
	    }
    }
    printf("%d\n" ,dp[n][m]);
    return 0;
}
posted @ 2021-06-15 20:16  24Kmagic  阅读(318)  评论(0)    收藏  举报