洛谷 P2758 编辑距离 题解

P2758 编辑距离

题目描述

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

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

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

输入格式

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

输出格式

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

输入输出样例 #1

输入 #1

sfdqxbw
gfdgw

输出 #1

4

说明/提示

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

题解

考虑动态规划。
设字符串为\(a, b\),长度分别为\(n, m\)
定义\(dp_{i, j}\)是字符串\(a\)\(i\)个字符转换到字符串\(b\)\(j\)个字符所需要的最小操作次数。
那么就有

\[dp_{i, j} = \begin{cases} 0, & i = 0, j = 0 \\ dp_{i, j - 1} + 1, &i = 0, 1 \le j \le m \\ dp_{i - 1, j} + 1, & 1 \le i \le n, j = 0 \\ \min\{dp_{i, j - 1} + 1, dp_{i - 1, j} + 1, dp_{i - 1, j - 1} + k\}, &Others \end{cases} \]

#include <bits/stdc++.h>
#define endl "\n"
#define int long long
using namespace std;
const int N = 2e3 + 5;
string a, b;
int dp[N][N];
signed main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> a >> b;
  memset(dp, 0, sizeof dp);
  for (int i = 0; i <= a.size(); i++) {
    for (int j = 0; j <= b.size(); j++) {
      if (i == 0 && j == 0) {
        dp[i][j] = 0;
      } else if (i == 0) {
        dp[i][j] = dp[i][j - 1] + 1;
      } else if (j == 0) {
        dp[i][j] = dp[i - 1][j] + 1;
      } else {
        dp[i][j] = min(dp[i - 1][j] + 1,
                       min(dp[i][j - 1] + 1,
                           dp[i - 1][j - 1] + (a[i - 1] == b[j - 1] ? 0 : 1)));
      }
    }
  }
  cout << dp[a.size()][b.size()] << endl;
  return 0;
}
posted @ 2025-03-03 20:35  Terminal_P  阅读(7)  评论(0编辑  收藏  举报