文本比较算法2

 

<script type="text/javascript"> document.body.oncopy = function() { if (window.clipboardData) { setTimeout(function() { var text = clipboardData.getData("text"); if (text && text.length>300) { text = text + "/r/n/n本文来自CSDN博客,转载请标明出处:" + location.href; clipboardData.setData("text", text); } }, 100); } } </script> <script class="blogstory">function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>

上回说到,如何确定最大匹配数。接下来,本次将简述如何确定最优匹配路径。仿照确定最大匹配数的算法,这个问题也非常容易解决,不知道这周当中,有没有哪位 XDJM 已经有了自己的解决方案呢?

有问题可以发邮件给我: Calriones@hotmail.com

文本比较算法剖析( 2 - 如何确定最优匹配路径

确定最优匹配路径的问题,通常在做文件比较时要用到,它的意思是:在所有能够得到最大匹配点数的路径中,找出一条最短的路径。

让我们继续以上次的例子进行研究:

 

首先,我们仍然是手工标出能够得到最大匹配点数的所有路径。在手工绘制可用路径的时候,需要说明一下:

l          首先,这里我们以计算 left 的最优路径为例。计算 right 的最优路径和 left 是完全对称的;

l          在图中,向右移动一格,表示 left 的当前元素放弃和 right 的当前元素进行匹配,而和 right 的下一个元素进行匹配。如果进行文件比较的话,就是 left 文件的当前行前,插入 right 文件的当前行;

l          在图中,向下移动一格,表示 left 的当前元素放弃和 right 的当前元素进行匹配,而使用 left 的下一个元素和 right 的当前元素进行匹配。如果进行文件比较的话,就是 left 文件的当前行被删除;

l          在途中,向右下方移动一格,表示确定 left right 的当前元素的匹配,使用 left 的下一个元素和 right 的下一个元素进行匹配。如果进行文件比较的话,就是 left right 文件的当前行已经匹配,分别比较下一行。

l          由于 left right 是流式的,所以每个元素只能匹配一次而且不能颠倒顺序,所以,在 x y 方向上,只能保留一个匹配点,而且只能向下,向右,或者向右下方移动。

 

有了这些规则,我们就可以得到如下图中间红色粗线所示的 4 条可能的路径。

 

从上向下,依次编号为 1,2,3,4 号路径,分析如下:

1 号路径表示(只说明含义,算法推导在后面):

依次类推,可以得到其他路径的实际含义。需要说明的是, 3 号路径在选择第二个匹配点时,没有采用 left[9]:right[1] 的匹配关系,而是跳过 left[9] ,采用了 left[11]:right[1] 。这样,点 (left[9], right[1]) 3 号路径上是“删除 left 9 行”的意思。

如果我将整个过程中在 left 上移动的距离纪录下来,就得到:

从图上就很容易看出,在 left 上移动最短的,也就是最优的路径,是 4 号路径。

是不是看起来毫无头绪?

别急,象上次一样,我们进行一个分析。

依然是归纳法,依然是找出元素 D(l,r) 3 个相邻区域 A,B,C:

分析:

1.          如果点 D(l,r) 表示从 left 的第 L 个元素, right 的第 R 个元素出发,匹配到矩阵边界后,在 left 方向上的最短路径长度 (我更喜欢称之为 depth ,那么:

2.          如果点 (l,r) 是一个被确定的匹配点,那么下一步,只能选择进入 A 区域,到点 (l+1,r+1) ,所以得到:

D1       If (V(l,r)>0) then D(l,r) = 1 + D(l+1,r+1)
还记得 V(l,r) N(l,r) 的定义么?可以看看文档《文本比较算法剖析( 1 - 如何确定最大匹配率

3.          如果点 (l,r) 不是一个被确定的匹配点,那么下一步可以进入 B 或者 C.

D2       如果进入 B 区域,那么意味着 插入 right 的第 r ,但是在 left 的位置保持不变,所以得到:
If (V(l,r) == 0) then D(l,r) = D(l,r+1)

D3       如果进入 C 区域,那么意味着 删除 left 的第 l ,在 right 的位置保持不变,但是在 left 的位置要加 1 。所以得到 :
If (V(l,r) == 0) then D(l,r) = 1 + D(l+1,r)

那么现在有 3 个值 D1 D2 D3 ,该如何取舍呢?直接取 Min(D1,D2,D3) 可以么?

 

呵呵,其实,我也是尝试了很多次以后才搞清楚的。大家可以用 excel 验证一下自己的想法。很简单的,大概验证整个算法,用 10 行左右的代码再加上 excel 本身提供的公式就足够了。

 

4.          不要忘记了前面说过的, 在所有能够得到最大匹配点数的路径中,找出一条最短的路径 ”, 首先我们要保证得到最大匹配匹配点数,所以我们又有:

If (N(l,r+1) >= N (l+1,r) then

D(l,r) = D(l,r+1);

Else

   D(l+r) = 1 + D(l+1,r)

综合上面所有的分析,路径长度 D(l,r) 的计算公式就是:
    If (V(l,r) = 1) Then

        D(l,r) = D(l+1,r+1) + 1

    Else

        If (N(l,r+1) >= N(l+1,r)) Then

            D(l,r) = D(l,r+1)

        Else

            D(l,r) = D(l+1,r) + 1

        End If

将公式写入 excel 自动计算,得到结果如图:

可以看到,结果正确。

 

OK 结束了,文本比较的算法核心就介绍完了。

事实上,上面第四步给出的是优化后的结果,有兴趣的可以自己试着分析一下第 4 步是否应该这样计算,有什么情况我没有在这里讲的,但是结果为什么又是正确的。

 

有了这个算法,大家可以很快的编写自己的文本比较功能了。

计算最优路径的附加时间复杂度为 0 ,因为它完全可以和计算最大匹配点数一起进行;附加的空间复杂度为 Max(m,n), 因为它需要一个额外的数组纪录 N(l+1)

 

如果不计算最优路径的话,计算最大匹配点数的算法还可以再优化。

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值