最短编辑距离
题目:
给定两个字符串 A 和 B,现在要将 A 经过若干操作变为 B,可进行的操作有:
删除–将字符串 A 中的某个字符删除。
插入–在字符串 A 的某个位置插入某个字符。
替换–将字符串 A 中的某个字符替换为另一个字符。
现在请你求出,将 A 变为 B 至少需要进行多少次操作。

1.状态表示 :f[i][j] 代表a字符串前i个字符替换成b字符串前j个的最小操作
集合:将a[1i]变成b[1j]的操作方式
属性:min
2.状态计算
有三种操作,所以有三个子集
考虑状态转移的时候
先考虑如果我没有进行这个操作应该是什么状态
然后考虑你进行这一步操作之后会对你下一个状态造成什么影响
然后再加上之前状态表示中你决策出来的那个DP属性
1)删除操作:把a[i]删掉之后a[1i]和b[1j]匹配
所以之前要先做到a[1(i-1)]和b[1j]匹配
f[i-1][j] + 1
2)插入操作:插入之后a[i]与b[j]完全匹配,所以插入的就是b[j]
那填之前a[1i]和b[1(j-1)]匹配
f[i][j-1] + 1
3)替换操作:把a[i]改成b[j]之后想要a[1i]与b[1j]匹配
那么修改这一位之前,a[1(i-1)]应该与b[1(j-1)]匹配
f[i-1][j-1] + 1
但是如果本来a[i]与b[j]这一位上就相等,那么不用改,即
f[i-1][j-1] + 0
f[i][j]就由以上三个可能状态转移过来,取个min
初始化问题
f[0][i]如果a初始长度就是0,那么只能用插入操作让它变成b
f[i][0]同样地,如果b的长度是0,那么a只能用删除操作让它变成b
code:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e3 + 10;
int f[N][N];
char a[N],b[N];
int main(){
int n, m;
cin >> n >> a + 1;
cin >> m >> b + 1;
// f[i][0]同样地,如果b的长度是0,那么a只能用删除操作让它变成b
for (int i = 0; i <= n; i ++)
f[i][0] = i;
// f[0][i]如果a初始长度就是0,那么只能用插入操作让它变成b
for (int i = 0; i <= m; i ++)
f[0][i] = i;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
{
f[i][j] = min(f[i - 1][j] + 1, f[i][j - 1] + 1);
// f[i][j]继承的上一步操作,所以后续判断不能直接让f[i][j] = f[i - 1][j - 1];
if (a[i] == b[j]) f[i][j] = min(f[i][j], f[i - 1][j - 1]);
else f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1);
}
cout << f[n][m];
return 0;
}

浙公网安备 33010602011771号