1225: 字符串的修改

这里写图片描述
链接在这儿!

这其实是一道经典的题目——Edit distance

很自然地我们会想到,变换两个字符串所需的操作次数与这两个字符串的匹配程度有关。

举个栗子 SNOWY & SUNNY
以下是几种可能的情况
S – N O W Y
S U N N – Y
操作数:3

– S N O W – Y
S U N – – N Y
操作数:5

“–”意味着一次插入删除操作。

当它们匹配程度最高时,便会有最小的操作数产生,如果你枚举的话,可以发现,第一种修改情况的操作数是最少的,没有比这更少的操作数:插入 U ,将 ON,删除 W

总而言之,两个字符串之间有很多种匹配方案,如果暴力搜索无疑是低效的。

在这里,我们引入一个全新的思考问题的视角:

我们把输入的两个字符串 xm yn 表示为 x[1m] y[1n](m,nxy)

想象一下,假设我们已经获得 x[1i1]y[1j1] x[1i]y[1j1] x[1i1]y[1j] 匹配时的最小操作数,分别记为 dp(i1,j1)dp(i,j1)dp(i1,j)
此时当我们要匹配 x[1i]y[1j] 时,我们会面临如下3种选择:

1.删除 x[i]

x[i]

2.插入y[j]


y[j]

3. x[i]y[j]

x[i]
y[j]

以下重点!
以第一种情况为例:删除 x[i] ,操作数为 1 ,那么此时x的长度为 i1 ,很容易想到,此时的总操作数 dp(i,j) 恰恰就是在已知的 dp(i1,j) 的基础上 +1 ,同理第二、三种情况可得类似的结果。

题目要求最少的操作数,那么我们最好的方案便是在每一步时都求得最少的操作数,按以上思路继续,便可获得整体最小的操作数。(由于以上式子 i,j 1...m,1...n 中任意一个数,故以上思路存在普遍性

dp(i,j)=min{dp(i1,j)+1,dp(i,j1)+1,dp(i1,j1)+diff(i,j)}

其中,当 x[i]!=y[i] 时, diff(i,j)=1 ,表示需要一次修改操作;当 x[i]==y[i] 时, diff(i,j)=0 ,表示此时不需要修改操作

如此,我们刚好可以用一个二维数组 dp[i][j] 表示 dp(i,j) ,让 i,j 分别从小到大循环,来处理 x[i] y[i] 的情形。最后 dp[m][n] 即为所求的最小值。

伪代码可以这么写
for i=0,1,2,...,m:
       dp[i][0]=i
for j=0,1,2,...,n:
       dp[0][j]=j
for i=1,2,...,m:
       for j=1,2,...,n:
              dp(i,j)=min{dp(i1,j)+1,dp(i,j1)+1,dp(i1,j1)+diff(i,j)}

其实这种方法叫做动态规划 Dynamic programming,dp是它的缩写,同学们可以自己去了解一下这种思想方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值