问题描述
定义
给定两个序列: X = ( x 1 , x 2 , . . . , x m ) X=(x_1,x_2,...,x_m) X=(x1,x2,...,xm), Y = ( y 1 , y 2 , . . . , y n ) Y=(y_1,y_2,...,y_n) Y=(y1,y2,...,yn)。求使得 X X X变为 Y Y Y的最少以下操作数目:
- 插入一个元素
- 删除一个元素
- 替换一个元素
注:这里定义的三种操作的权重是一样的,有时候不是这样,比如会将替换操作的权重设为2,相当于删除一个元素后再插入一个元素。
研究动机与应用
- 拼写纠错:可能的情况:打错、少打、多打;
- 计算生物学:DNA碱基序列比对;
- 机器翻译、信息提取、语言识别等。
动态规划求解
第一步:定义最优解
定义 d i , j d_{i,j} di,j为从序列 X [ 1 , … , i ] X[1,\dots,i] X[1,…,i]到序列 Y [ 1 , … , j ] Y[1,\dots,j] Y[1,…,j]的最小编辑操作次数。
第二步:建立递推关系
我们从两个序列的末尾开始向开头进行递推,这样在后续自底向上填表时就能从序列头进行填写。
从序列
X
[
1
,
…
,
i
]
X[1,\dots,i]
X[1,…,i]到序列
Y
[
1
,
…
,
j
]
Y[1,\dots,j]
Y[1,…,j],有如下三种编辑方法。
方法一:通过插入
Y
[
j
]
Y[j]
Y[j]实现。即先解决从
X
[
1
,
.
.
.
,
i
]
X[1,...,i]
X[1,...,i]到
Y
[
1
,
.
.
.
,
j
−
1
]
Y[1,...,j-1]
Y[1,...,j−1]的子问题,再进行一次插入操作。递推关系为:
d
i
,
j
=
d
i
,
j
−
1
+
1
d_{i,j}=d_{i,j-1}+1
di,j=di,j−1+1
方法二:通过删除
X
[
i
]
X[i]
X[i]实现。即先解决从
X
[
1
,
.
.
.
,
i
−
1
]
X[1,...,i-1]
X[1,...,i−1]到
Y
[
1
,
.
.
.
,
j
]
Y[1,...,j]
Y[1,...,j]的子问题,再进行一次删除操作。递推关系为:
d
i
,
j
=
d
i
−
1
,
j
+
1
d_{i,j}=d_{i-1,j}+1
di,j=di−1,j+1
方法三:通过将
X
[
i
]
X[i]
X[i]替换为
Y
[
j
]
Y[j]
Y[j]实现。即先解决从
X
[
1
,
.
.
.
,
i
−
1
]
X[1,...,i-1]
X[1,...,i−1]到
Y
[
1
,
.
.
.
,
j
−
1
]
Y[1,...,j-1]
Y[1,...,j−1]的子问题,再进行一次替换操作。当然,如果最后一个元素是相同的就不用替换了。递推关系为:
d
i
,
j
=
{
d
i
−
1
,
j
−
1
+
1
(
X
[
i
]
≠
Y
[
j
]
)
d
i
−
1
,
j
−
1
(
X
[
i
]
=
Y
[
j
]
)
d_{i,j}=\begin{cases}d_{i-1,j-1}+1(X[i]\neq Y[j])\\d_{i-1,j-1}(X[i]=Y[j])\end{cases}
di,j={di−1,j−1+1(X[i]=Y[j])di−1,j−1(X[i]=Y[j])
综上所述,递推关系为:
d
i
,
j
=
m
i
n
{
d
i
,
j
=
d
i
,
j
−
1
+
1
d
i
,
j
=
d
i
−
1
,
j
+
1
d
i
−
1
,
j
−
1
+
{
1
(
X
[
i
]
≠
Y
[
j
]
)
0
(
X
[
i
]
=
Y
[
j
]
)
d_{i,j}=min\begin{cases} d_{i,j}=d_{i,j-1}+1\\ d_{i,j}=d_{i-1,j}+1\\ d_{i-1,j-1}+\begin{cases}1(X[i]\neq Y[j])\\0(X[i]=Y[j])\end{cases}\\ \end{cases}
di,j=min⎩
⎨
⎧di,j=di,j−1+1di,j=di−1,j+1di−1,j−1+{1(X[i]=Y[j])0(X[i]=Y[j])
第三步:自底向上计算(填表)
以 X = A B C B D A B X=ABCBDAB X=ABCBDAB, Y = B D C A B A Y=BDCABA Y=BDCABA为例。
先填好第一行和第一列:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 1 | ||||||
2 | 2 | ||||||
3 | 3 | ||||||
4 | 4 | ||||||
5 | 5 | ||||||
6 | 6 | ||||||
7 | 7 |
x 1 ≠ y 1 x_1\neq y_1 x1=y1,故 d 1 , 1 = m i n { d 0 , 1 + 1 , d 1 , 0 + 1 , d 0 , 0 + 1 } d_{1,1}=min\{d_{0,1}+1,d_{1,0}+1,d_{0,0}+1\} d1,1=min{d0,1+1,d1,0+1,d0,0+1}
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 1 | 1 | |||||
2 | 2 | ||||||
3 | 3 | ||||||
4 | 4 | ||||||
5 | 5 | ||||||
6 | 6 | ||||||
7 | 7 |
…
x 7 ≠ y 6 x_7\neq y_6 x7=y6,故 d 7 , 6 = m i n { d 7 , 5 + 1 , d 6 , 6 + 1 , d 6 , 5 + 1 } d_{7,6}=min\{d_{7,5}+1,d_{6,6}+1,d_{6,5}+1\} d7,6=min{d7,5+1,d6,6+1,d6,5+1}
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 1 | 1 | 2 | 3 | 3 | 4 | 5 |
2 | 2 | 1 | 2 | 3 | 4 | 3 | 4 |
3 | 3 | 2 | 2 | 2 | 3 | 4 | 4 |
4 | 4 | 3 | 3 | 3 | 3 | 3 | 4 |
5 | 5 | 4 | 3 | 4 | 4 | 4 | 4 |
6 | 6 | 5 | 4 | 4 | 4 | 5 | 4 |
7 | 7 | 6 | 5 | 5 | 5 | 4 | 5 |
故MED=5。
第四步:最优方案追踪
如果需要进行最优方案的记录,应该与第三步同时进行,这里为便于书写而分开。为了追踪最优方案,应该记录每次递推时是从
d
i
−
1
,
j
−
1
d_{i-1,j-1}
di−1,j−1,
d
i
−
1
,
j
−
1
d_{i-1,j-1}
di−1,j−1还是
d
i
,
j
−
1
d_{i,j-1}
di,j−1得来,分别采取的操作是什么。建立追踪表,如果是从左上角推得(即替换操作),填写LU
;如果是从左边(即插入操作),填写L
;如果是从上面推得(即删除操作),填写U
。
先填好第一行和第一列。第一行全是插入操作,第一列全是删除操作:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
0 | x | L | L | L | L | L | L |
1 | U | ||||||
2 | U | ||||||
3 | U | ||||||
4 | U | ||||||
5 | U | ||||||
6 | U | ||||||
7 | U |
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
0 | x | L | L | L | L | L | L |
1 | U | LU | |||||
2 | U | ||||||
3 | U | ||||||
4 | U | ||||||
5 | U | ||||||
6 | U | ||||||
7 | U | ||||||
… |
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
0 | x | L | L | L | L | L | L |
1 | U | LU | LU | LU | LU | L | LU |
2 | U | LU | LU | LU | LU | LU | L |
3 | U | U | LU | LU | L | L | LU |
4 | U | LU | LU | LU | LU | LU | L |
5 | U | U | LU | LU | LU | LU | LU |
6 | U | U | U | LU | LU | LU | LU |
7 | U | LU | U | LU | LU | LU | L |
从
d
7
,
6
d_{7,6}
d7,6倒推得到的序列为:U
,LU
(eql),U
,LU
,LU
,LU
(eql),LU
(eql),L
LU
(eql)表示对应字符相等,什么都不用做。
故从
X
X
X到
Y
Y
Y的5个编辑操作依次为:删除
X
[
1
]
X[1]
X[1],删除
X
[
3
]
X[3]
X[3],替换
X
[
4
]
X[4]
X[4]为
D
D
D,替换
X
[
5
]
X[5]
X[5]为
C
C
C,在
X
[
7
]
X[7]
X[7]之后插入
A
A
A。
简单讨论:带权的MED问题
如果将替换操作的权重设为2(记为方案一),那么该情况是否与仅有插入和删除操作的情况等价(记为方案二)?答案是肯定的。
证明:
- 方案一在方案二的基础上提供了新的操作,且完全可以采取方案二已有的操作。因此方案一的MED一定小于等于方案二的MED。
- 方案一的一次替换操作可以由方案二的一次插入和一次删除操作替换,代价相同。因此凡是方案一种用到替换操作的地方都可以等代价地将其替换为方案二的操作。因此方案二的MED一定小于等于方案一的MED。
- 综上所述,方案一和二的MED一定相等。
容易进一步证明,只要替换操作的权重 ≥ \geq ≥ 2,这两种方案都是等价的。