题目传送门[(https://www.luogu.com.cn/problem/P2758)]
题目描述
设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:
1、删除一个字符;
2、插入一个字符;
3、将一个字符改为另一个字符;
!皆为小写字母!
输入格式
第一行为字符串A;第二行为字符串B;字符串A和B的长度均小于2000。
输出格式
只有一个正整数,为最少字符操作次数。
输入输出样例
输入 #1
sfdqxbw
gfdgw
输出 #1
4
解
注意到删除A[i] 等价于 在B[i]前 插入
在A[i]前插入与B[i]相同的元素 等价于 删除 B[i]
修改A[i] 等价于 修改B[i]
为啥?
因为这样的两种操作,都增加了一次操作次数,最终带来了同样的结果
所以,我们只需要对一个串操作,最终的结果没有影响
只对B操作
f[i][j]表示要使A的前i个元素与B的前j个元素相同的最少操作次数
初始化
f[i][0] = i;
f[0][j] = j;
转移
如果A[i]等于B[i],不做修改,f[i][j] = f[i - 1][j - 1]
否则,三种修改方式,在B中加一个,f[i][j] = f[i - 1][j] + 1;
在B中删一个,f[i][j] = f[i][j - 1] + 1;
在B中改一个,f[i][j] = f[i - 1][j - 1] + 1;
三者取max
代码
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 2010
#define INF 1061109000
using namespace std;
int f[N][N], n1, n2;
string a , b;
int main()
{
cin >> a >> b;
for (int i = 0 ; i <= a.size() ; i++)
{
for (int j = 0 ; j <= b.size() ; j++)
f[i][j] = INF;
}
f[0][0] = 0;
f[0][1] = 1;
f[1][0] = 1;
for (int i = 0 ; i <= a.size() ; i++) f[i][0] = i;//重要的初始化
for (int j = 0 ; j <= b.size() ; j++) f[0][j] = j;//重要的初始化
//只编辑b[]
for (int i = 1 ; i <= a.size() ; i++)
{
for (int j = 1 ; j <= b.size() ; j++)
{
if(a[i - 1] == b[j - 1])
{
f[i][j] = f[i - 1][j - 1];
// cout << i << " " << j << " " << f[i][j] << endl;
continue;
}
f[i][j] = min(f[i][j], f[i - 1][j - 1] +1);
f[i][j] = min(f[i][j], f[i][j - 1] + 1);
f[i][j] = min(f[i][j], f[i - 1][j] + 1);
// cout << i << " " << j << " " << f[i][j] << endl;
}
}
/* for (int j = 1 ; j <= a.size() ; j++)
{
for (int i = 1 ; i <= b.size() ; i++) cout << f[j][i] << " ";
cout << endl;
}
*/
cout << f[a.size()][b.size()] << endl;
return 0;
}