动态规划:最短编辑距离

题目链接

P2758 编辑距离

题目描述

A A A B B B 是两个字符串。我们要用最少的字符操作次数,将字符串 A A A 转换为字符串 B B B。这里所说的字符操作共有三种:

  1. 删除一个字符;
  2. 插入一个字符;
  3. 将一个字符改为另一个字符。

A , B A, B A,B 均只包含小写字母。

输入格式

第一行为字符串 A A A;第二行为字符串 B B B;字符串 A , B A, B A,B 的长度均小于 2000 2000 2000

输出格式

只有一个正整数,为最少字符操作次数。

样例 #1

样例输入 #1

sfdqxbw
gfdgw

样例输出 #1

4

提示

对于 100 % 100 \% 100% 的数据, 1 ≤ ∣ A ∣ , ∣ B ∣ ≤ 2000 1 \le |A|, |B| \le 2000 1A,B2000

算法思想

  • 状态表示
    f[i][j]表示将字符串 A A A中前i个字符编辑成字符串 B B B中前j个字符所要进行的最少操作次数。

  • 状态计算,根据最后一步的情况,可以将操作分为 3 3 3类:

    1. 删除字符 A i A_i Ai使得两个字符串相匹配,那么要先做到 A [ 1... i − 1 ] A[1...i-1] A[1...i1] B [ 1... j ] B[1...j] B[1...j]相同,因此操作次数为f[i-1][j] + 1
    2. 插入字符 B j B_j Bj使得两个字符串相匹配,那么要先做到 A [ 1... i ] A[1...i] A[1...i] B [ 1... j − 1 ] B[1...j-1] B[1...j1]相同,因此操作次数为f[i][j-1] + 1
    3. 替换字符 A i A_i Ai B j B_j Bj使得字符串相匹配,又需要分两种情况讨论:
      • A i = B j A_i=B_j Ai=Bj,操作次数f[i-1][j-1]
      • A i ≠ B j A_i\ne B_j Ai=Bj,操作次数f[i-1][j-1] + 1

    最终,f[i][j] 应取以上三种情况的最小值。

  • 初始状态:

    1. f[0][i] = i,字符串A中插入i个字符
    2. f[i][0] = i,字符串A中删除i个字符

时间复杂度

状态数为 O ( n × m ) O(n\times m) O(n×m),状态计算过程为O(1)

代码实现

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2010;
char a[N], b[N];
int f[N][N];
int main()
{
    cin >> a + 1 >> b + 1;
    int n = strlen(a + 1), m = strlen(b + 1);
    //初始状态
    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], f[i][j - 1]) + 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少儿编程乔老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值