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;
}
posted @ 2021-06-15 20:08  Last-Order  阅读(43)  评论(0编辑  收藏  举报