开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情
题目描述
设 和 是两个字符串。我们要用最少的字符操作次数,将字符串 转换为字符串 。这里所说的字符操作共有三种:
- 删除一个字符;
- 插入一个字符;
- 将一个字符改为另一个字符。
均只包含小写字母。
输入格式
第一行为字符串 ;第二行为字符串 ;字符串 的长度均小于 。
输出格式
只有一个正整数,为最少字符操作次数。
input
sfdqxbw
gfdgw
output
4
提示
对于 的数据,。
题目分析
本题为线性DP,首先我们定义数组 表示使长度为 的字符串 的前 个字符和长度为 的字符串 的前 个字符完全匹配的最少操作步骤。
现在我们来模拟三种操作所对应的做法。
删除 中末尾字符
假设此时 的前 个字符与 的前 个字符已经匹配,则执行当前步骤后的操作数应为 。
向 末尾增加一个字符
假设此时 的前 个字符与 的前 个字符已经匹配,则执行当前步骤后的操作数应为 。
将 的末尾字符改为 的末尾字符。
假设此时 的前 个字符与 的前 个字符已经匹配。此时需要考虑两种情况。
若 ,则 。
若 则 。
我们枚举以上三种情况,取三种情况的最少操作数作为 的值,再进行之后操作。
最终答案为 。
Accept代码(DP)
#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
int f[N][N];
int main()
{
string a, b;
cin >> a >> b;
a = ' ' + a, b = ' ' + b;
int n = a.size(), m = b.size();
for (int i = 1; i <= n; i ++) f[i][0] = i;
for (int i = 1; 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);
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;
}