题解:编辑距离
题目
题目描述
设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;
}

浙公网安备 33010602011771号