2021.06.15 DP-编辑距离
题意
设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:
- 删除一个字符;
- 插入一个字符;
- 将一个字符改为另一个字符;
数据范围:\(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]\))
- 若进行删除\(a[i]\),则:
- 所以:\(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;
}