算法分析与设计(二)

动态规划

  • 编辑距离(Levenshtein距离)

比较两个字符串时,若字符串 x x x长度为m,字符串 y y y长度为n。
假设这两个字符串之间的编辑距离为 E ( m , n ) E(m,n) E(m,n)
要通过动态规划的方式解决它,那就需要将这样一个问题划分为子问题 E ( i , j ) E(i,j) E(i,j),子问题表示串 x x x中前 i i i个字符与串 y y y中前 j j j个字符之间的编辑距离。
当计算子串的编辑距离时,子串的最右边一列对齐时有以下三种情形:

  _ x [ i ] x [ i ] y [ j ] _ y [ j ] \ \_ \qquad \qquad x[i] \qquad \qquad x[i] \\ y[j] \qquad \qquad \_ \qquad \qquad y[j]  _x[i]x[i]y[j]_y[j]

根据以上的对齐方式,可以得到 E ( i , j ) E(i,j) E(i,j)的递推公式:

E ( i , j ) = m i n { 1 + E ( i − 1 , j ) ,   1 + E ( i , j − 1 ) ,   d i f f ( i , j ) + E ( i − 1 , j − 1 ) } ; I f   x [ i ] = = y [ i ]   t h e n   d i f f ( i , j ) = 0 ,   o t h e r w i s e   d i f f ( i , j ) = 1 ; E ( 0 , j ) = j ;   E ( i , 0 ) = i E(i,j) = min\{ 1+E(i-1,j), \ 1+E(i,j-1), \ diff(i,j)+E(i-1,j-1) \} ; \\ If \ x[i]==y[i] \ then \ diff(i,j)=0,\ otherwise \ diff(i,j)=1; \\ E(0,j)=j; \ E(i,0)=i E(i,j)=min{1+E(i1,j), 1+E(i,j1), diff(i,j)+E(i1,j1)};If x[i]==y[i] then diff(i,j)=0, otherwise diff(i,j)=1;E(0,j)=j; E(i,0)=i

根据以上递推公式,便能计算并填写下列表格,最终的 E ( m , n ) E(m,n) E(m,n)即为最小编辑距离

E ( i , j ) E(i,j) E(i,j)x[1]x[2]x[i]x[m]
012im
y[1]1
y[2]2
y[j]j
y[n]n

计算编辑距离的时间复杂度为
O ( m ⋅ n ) O(m \cdot n) O(mn)

计算出编辑距离后,要想求出字符串的编辑位置,则可以从 E ( m , n ) E(m,n) E(m,n)开始与左边、上边或左上角移动一格的区域中找出最小的一个编辑距离即 E d m i n = m i n { E ( m − 1 , n ) ,   E ( m , n − 1 ) ,   E ( m − 1 , n − 1 ) } Ed_{min}=min\{ E(m-1,n), \ E(m,n-1), \ E(m-1,n-1) \} Edmin=min{E(m1,n), E(m,n1), E(m1,n1)},将其与 E ( m , n ) E(m,n) E(m,n)比较,若两者相等则说明 x [ m ] x[m] x[m] y [ n ] y[n] y[n]是对齐且相等的;否则认为这一位置是编辑点。同时继续以 E d m i n Ed_{min} Edmin对应的位置开始继续以上的步骤。
?
如下图说示,为两字符串的编辑位置。

在这里插入图片描述

  • 邮差问题

给定一个加权完全图 G = ( V , E ) G=(V,E) G=(V,E),每条边都有对应一个权值。试寻找一个简单的环路(不闭合),这个环路经过每个顶点恰好一次,并且总权值最小。
如下所示的图,图中有 n = 5 n=5 n=5个顶点,假设起点是A点,则从起点开始逐一访问其余顶点形成的所有可能路径是其余4个点的排列 P ( n − 1 n − 1 ) P(^{n-1}_{n-1}) P(n1n1),使用动态规划的话,能

在这里插入图片描述

动态规划的解法思路是:
对于一个子集 S ⊆ { 1 , 2 , . . . , n } S\subseteq \{ 1,2,...,n\} S{1,2,...,n} 1 ∈ S , j ∈ S . 1 \in S , j \in S. 1S,jS.
C ( S , j ) C(S, j) C(S,j)表示从起点 1 1 1开始经过了集合 S S S中所有顶点一次且终止于 j j j的路径的最短长度。将 C ( S , j ) C(S, j) C(S,j)表示为更小的子问题:
C ( S , j ) = m i n C ( S − { j } , i ) + d i j C ( { 1 } , 1 ) = 0 C(S, j) = min C(S- \{ j \}, i) + d_{ij} \\ C(\{ 1\} ,1)=0 C(S,j)=minC(S{j},i)+dijC({1},1)=0

有了以上的递推公式,便能进行相应的动态规划算法设计了,先从大小为2的集合 S ( ∣ S ∣ = 2 , 且 起 点 1 ∈ S ) S (|S|=2, 且起点1 \in S) S(S=2,1S)开始,赋值 C ( S , 1 ) = ∞ C(S, 1) = \infty C(S,1)=,找出 S S S中的元素 j ( j ≠ 1 , j 非 起 点 ) j(j \neq1,j非起点) j(j̸=1j),对 C ( S , j ) C(S,j) C(S,j)执行上述递推公式。之后逐渐扩大集合S的大小直至 n n n,并重复上述步骤。

伪代码:
C ( { 1 } , 1 ) = 0 C(\{ 1\} ,1)=0 C({1},1)=0
for h=2 to n do
for all subsets S ⊆ { 1 , 2 , . . . , n } S \subseteq \{1,2,...,n \} S{1,2,...,n} of size h and containing 1 do
   C ( S , 1 ) = ∞ C(S,1) = \infty C(S,1)=
   for all j ∈ S , j ≠ 1 j \in S, j \neq 1 jS,j̸=1 do
    C ( S , j ) = m i n C ( S − { j } , i ) + d i j C(S, j) = min C(S- \{ j \}, i) + d_{ij} C(S,j)=minC(S{j},i)+dij
return m i n j C ( { 1 , 2 , . . . , n } , j ) + d j 1 min_j C( \{ 1,2,...,n \}, j) +d_{j1} minjC({1,2,...,n},j)+dj1

这种算法思路清晰,但是在实现算法的时候,需要设计合适ADT来表示图及顶点集合,我尝试过编写代码,但限于没有较好的ADT实现思路,我便放弃了 ?。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值