洛谷 P2758 编辑距离
Description
设 \(A\) 和 \(B\) 是两个字符串。我们要用最少的字符操作次数,将字符串 \(A\) 转换为字符串 \(B\)。这里所说的字符操作共有三种:
-
删除一个字符;
-
插入一个字符;
-
将一个字符改为另一个字符。
求转换的最少操作次数。
\(lenA,lenB \le 2000\),且均只包含小写字母。
Solution
考虑设 \(f[i][j]\) 表示把 \(A\) 中前 \(i\) 个字符变成 \(B\) 中前 j 个字符的最小步数,根据三种操作有转移:
- 增加:\(f[i - 1][j]\) --> \(f[i][j]\)
即在末尾添上一个与 \(B[j]\) 匹配的字符。
- 删除:\(f[i][j - 1]\) --> \(f[i][j]\)
即删掉末尾的那个字符。
- 修改:若 \(a[i] = b[j]\),\(f[i - 1][j - 1]\) --> \(f[i][j]\),否则 \(+1\)
初始值:\(f[i][0] = i\), \(f[0][i] = i\)。
如果两串的最后一位相同,我们就不需要花费一次操作,若不同,我们就需要操作一次,使得末尾位相同
Code
// by youyou2007 in 2022.
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#define REP(i, x, y) for(int i = x; i < y; i++)
#define rep(i, x, y) for(int i = x; i <= y; i++)
#define PER(i, x, y) for(int i = x; i > y; i--)
#define per(i, x, y) for(int i = x; i >= y; i--)
#define lc (k << 1)
#define rc (k << 1 | 1)
using namespace std;
/*
inline int read()
{
int s = 0, w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
*/
const int N = 2005;
string a, b;
int lena, lenb;
int f[N][N];
int main()
{
cin >> a >> b;
lena = a.length();
lenb = b.length();
a = "x" + a;
b = "x" + b;
for(int i = 1; i <= lena; i++)//初始值
{
f[i][0] = i;
}
for(int i = 1; i <= lenb; i++)
{
f[0][i] = i;
}
for(int i = 1; i <= lena; i++)
{
for(int j = 1; j <= lenb; j++)
{
f[i][j] = min(f[i - 1][j], 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);
}
}
printf("%d", f[lena][lenb]);
return 0;
}