P2758 编辑距离(7-7)

176 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情

P2758 编辑距离 - 洛谷

题目描述

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

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

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

输入格式

第一行为字符串 AA;第二行为字符串 BB;字符串 A,BA, B 的长度均小于 20002000

输出格式

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

input

sfdqxbw
gfdgw

output

4

提示

对于 100%100 \% 的数据,1A,B20001 \le |A|, |B| \le 2000

题目分析

本题为线性DP,首先我们定义数组 f[i][j]f[i][j] 表示使长度为 nn 的字符串 AA 的前 ii 个字符和长度为 mm 的字符串 BB 的前 jj 个字符完全匹配的最少操作步骤。

现在我们来模拟三种操作所对应的做法。

1.1. 删除 AA 中末尾字符

假设此时 AA 的前 ii 个字符与 BB 的前 j1j-1 个字符已经匹配,则执行当前步骤后的操作数应为 f[i][j]=f[i][j1]+1f[i][j] = f[i][j-1] + 1

2.2.AA 末尾增加一个字符

假设此时 AA 的前 i1i-1 个字符与 BB 的前 jj 个字符已经匹配,则执行当前步骤后的操作数应为 f[i][j]=f[i1][j]+1f[i][j] = f[i-1][j] + 1

3.3.AA 的末尾字符改为 BB 的末尾字符。

假设此时 AA 的前 i1i-1 个字符与 BB 的前 j1j-1 个字符已经匹配。此时需要考虑两种情况。

a[i]=b[j]a[i]=b[j],则 f[i][j]=f[i1][j1]f[i][j] = f[i-1][j-1]

a[i]!=b[j]a[i]!=b[j]f[i][j]=f[i1][j1]+1f[i][j] = f[i-1][j-1]+1

我们枚举以上三种情况,取三种情况的最少操作数作为 f[i][j]f[i][j] 的值,再进行之后操作。

最终答案为 f[n][m]f[n][m]

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;
}