1225: 字符串的修改

来源:互联网 发布:语音模拟软件 编辑:程序博客网 时间:2024/06/03 20:51

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

这其实是一道经典的题目——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

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

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

我们把输入的两个字符串 xmyn 表示为 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,j1...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是它的缩写,同学们可以自己去了解一下这种思想方法。

原创粉丝点击