[LuoGu] P2758 编辑距离

(color{red}{mathcal{Description}})

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

1、删除一个字符;

2、插入一个字符;

3、将一个字符改为另一个字符;

皆为小写字母

(color{red}{mathcal{Input Format}})

第一行为字符串 (A) ;第二行为字符串 (B)

(color{red}{mathcal{Output Format}})

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

(color{red}{mathcal{DataSize Agreement}})

字符串 (A)(B) 的长度均小于(2000)

(color{red}{mathcal{Solution}})

考虑用dp

(dp[i][j]) 表示字符串 (A) 的前 (i) 位转换为字符串 (B) 的前 (j) 位需要最小的操作次数

再考虑状态的转移.这里有个小弯,其实操作一与操作二可以归为一个状态,因为仔细想想就知道没有区别.

所以得出状态转移方程

[dp[i][j]=egin{cases}dp[i-1][j-1]&(A[i]=B[j])\max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1&(A[i] eq B[j])end{cases} (1 leq i leq lengthA, 1 leq j leq lengthB) ]

初始化 (dp[i][0]=i),(dp[0][j]=j) ((1 leq i leq lengthA, 1 leq j leq lengthB))

(color{red}{mathcal{Code}})

#include <bits/stdc++.h>
#define LL long long
#define reg register

using namespace std;

const int kLen = 2e3 + 10;

int dp[kLen][kLen];
char A[kLen], B[kLen];

int main() {
  scanf("%s%s", A + 1, B + 1);
  int lena = strlen(A + 1), lenb = strlen(B + 1);
  for (reg int i = 1; i <= lena; ++i)
    dp[i][0] = i;
  for (reg int i = 1; i <= lenb; ++i)
    dp[0][i] = i;
  for (reg int i = 1; i <= lena; ++i)
    for (reg int j = 1; j <= lenb; ++j) {
      if (A[i] == B[j]) {
      	dp[i][j] = dp[i - 1][j - 1];
	  } else {
	  	dp[i][j] = min(dp[i - 1][j], min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
	  }
	}
  printf("%d
", dp[lena][lenb]);
  return 0;
}

原文地址:https://www.cnblogs.com/1miharu/p/11328951.html