洛谷P2758 编辑距离

一,题目

# 编辑距离

## 题目描述

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

1. 删除一个字符;

2. 插入一个字符;

3. 将一个字符改为另一个字符。

$A, B$ 均只包含小写字母。

## 输入格式

第一行为字符串 $A$;第二行为字符串 $B$;字符串 $A, B$ 的长度均小于 $2000$。

## 输出格式

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

## 样例 #1

### 样例输入 #1

```

sfdqxbw

gfdgw

```

### 样例输出 #1

```

4

```

## 提示

对于 $100 \%$ 的数据,$1 \le |A|, |B| \le 2000$。

链接:P2758 编辑距离 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

二,思路建立一个编辑距离的转化矩阵dp,dp[i][j]代表字符串A的前i个字符串转字符串B前j个字符串所需要的最少步骤。

以sfdqxbw和gfdgw(注:s是sfdqxbw第一个字符串,不是第0个)为例子,下面是该矩阵表示含义:

B\A

i=0

i=1

i=2

i=3

i=4

i=5

i=6

i=7

j=0

/

/s

/sf

/sfd

/sfdq

/sfdqx

/sfdqxb

/sfdqxbw

j=1

g/

g/s

g/sf

g/sfd

g/sfdq

g/sfdqx

g/sfdqxb

g/sfdqxbw

j=2

gf/

gf/s

gf/sf

gf/sfd

gf/sfdq

gf/sfdqx

gf/sfdqxb

gf/sfdqxbw

j=3

gfd/

gfd/s

gfd/sf

gfd/sfd

gfd/sfdq

gfd/sfdqx

gfd/sfdqxb

gfd/sfdqxbw

j=4

gfdg/

gfdg/s

gfdg/sf

gfdg/sfd

gfdg/sfdq

gfdg/sfdqx

gfdg/sfdqxb

gfdg/sfdqxbw

j=5

gfdgw/

gfdgw/s

gfdgw/sf

gfdgw/sfd

gfdgw/sfdq

gfdgw/sfdqx

gfdgw/sfdqxb

gfdgw/sfdqxbw

对于i=0,j=0,都是空字符串,所以dp[0][0]=0;

对于i=0,j=1,B为g,A为空,把g插入A中可得B,所以dp[0][1]=1;

对于i=0,j=2,B=gf,A为空,把g和f插入A中可得B,所以dp[0][2]=2;

对于i=0,j=3,B=gfd,A为空,把g,f,d插入A中可得B,所以dp[0][3]=3;

对于i=0;j=4,B=gfdg,A为空,把gfdg插入A中可得B,所以dp[0][4]=4;

对于i=0,j=5,B=gfdgw,A为空,把gfdgw插入A中可得B,所以dp[0][5]=5;

对于j等于0的情况也是如此

所以dp[1][0]=1,dp[2][0]=2,dp[3][0]=3,dp[4][0]=4,dp[5][0]=5,dp[6][0]=6,dp[7][0]=7;

此时讨论对于i=1的情况

对于i=1,j=0,B为空,A为s,把s插入B中可得B,所以dp[1][0]=1;

对于i=1,j=1,B为g,A为s,此时可通过dp[0][1](B为g,A为空),dp[1][0](B为空,A为s),dp[0][0](A为空,B为空)到,即dp[1][1]转化为dp[0][1],dp[1][0]或dp[0][0]三者后,在根据这三者求最小步骤。根据题目,dp[1][1]转化为dp[0][1],只需要删除A中的s。dp[1][1]转化为dp[1][0],只需要删除B中的

g,dp[1][1]转化为dp[0][0],只需要改变A或B的值。所以dp[1][1]=max(dp[1][0]+1,dp[0][1]+1,dp[1][1]+1);

其他同理,所以一般来讲,dp[i][j]=max(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1);

但是如果A[i]=B[j],此时由于相同,我们不需要更改,所以自动忽略这两个字符,而去讨论这两个字符的前面的字符串,所以dp[i][j]=dp[i-1][j-1]

所以dp的表格是这样的

B\A

i=0

i=1

i=2

i=3

i=4

i=5

i=6

i=7

j=0

0

1

2

3

4

5

6

7

j=1

1

1

2

3

4

5

6

7

j=2

2

2

1

2

3

4

5

6

j=3

3

3

2

1

2

3

4

5

j=4

4

4

3

2

2

3

4

5

j=5

5

5

4

3

3

3

4

4

三,代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
#define inf 0x3f3f3f3f
int dp[2000][2000] = { 0 };
string str1, str2;
signed main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> str1 >> str2;
    int N = max(str1.size(), str2.size());
    for (int j = 1; j <= N; ++j) dp[j][0] = dp[0][j] = j;
    for (int j = 1; j <= str2.size(); ++j)
    {
        for (int i = 1; i <= str1.size(); ++i)
        {
            dp[j][i] = inf;
            if (str1[i - 1] == str2[j - 1]) dp[j][i] = dp[j - 1][i - 1];
            else dp[j][i] = min(min(dp[j - 1][i], dp[j][i - 1]), dp[j - 1][i - 1]) + 1;
        }
    }
    cout << dp[str2.size()][str1.size()];
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值