2021.06.15 DP-编辑距离

题意

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

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

数据范围:(len(a),len(b)le 2000)

解析

有:(dp[i][j])表示字符串A选取前(i)项,字符串B选取前(j)项所需要的最小价值。
所以对于(a[i])(b[j])

  • (a[i]==b[j]),代表(a[i])位与(b[j])位不需要被更改
    • 此时,可以直接从(a[i])前一位,与(b[j])前一位继承而来。
    • (dp[i][j]=dp[i-1][j-1]);
  • (a[i]!=b[j]),代表第(a[i])位与第(b[j])位需要被更改
    • 此时,需要进行操作:
      • 若进行删除(a[i]),则:
        • (dp[i][j]=dp[i-1][j]+1)(从(a[i])前一位继承而来)
      • 若进行插入字符,则:
        • (dp[i][j]=dp[i][j-1]+1)(插入(b[j])
      • 若进行修改操作,则:
        • (dp[i][j]=dp[i-1][j-1]+1)(直接将(a[i])修改为(b[j])
    • 所以:(dp[i][j] = min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1)

代码

#include <bits/stdc++.h>
#define fo(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;
const int INF = 0x3f3f3f3f , N = 2e3+5;
typedef long long ll;
typedef unsigned long long ull;
inline ll read(){
	ll ret = 0 ; char ch = ' ' , c = getchar();
	while(!(c >= '0' && c <= '9')) ch = c , c = getchar();
	while(c >= '0' && c <= '9')ret = (ret << 1) + (ret << 3) + c - '0' , c = getchar();
	return ch == '-' ? - ret : ret;
}
char a[N],b[N];
int n,m,dp[N][N];
signed main(){
	scanf("%s %s",a+1,b+1);
	n = strlen(a+1) , m = strlen(b+1);
	for(int i = 1 ; i <= n ; i ++) dp[i][0] = i;
	for(int i = 1 ; i <= m ; i ++) dp[0][i] = i;
	for(int i = 1 ; i <= n ; i ++)
		for(int j = 1 ; j <= m ; j ++)
			if(a[i] == b[j])
				dp[i][j] = dp[i-1][j-1];
			else
				dp[i][j] = min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1;
	printf("%d",dp[n][m]);
	return 0;
}
原文地址:https://www.cnblogs.com/Shinomiya/p/14886961.html