题意
设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;
}