文本比较算法1

 

<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>

最近看到有人在找关于文本比较的算法,刚好最近休假,研究了一下,终于找到一个简单有效的算法,和大家分享一下。

算法本身很简单,但是要说清楚思路和原理就比较复杂了,打算分两次发表(明天就要上班拉!),分别对应文本比较算法中的两个主要问题:

1。如何确定最大匹配率; 
2。如何确定最优的匹配路径;

算法本身是基于图论的,太麻烦了,所以不打算介绍整个思路,只将最后的结果详细解说给大家。有问题可以发邮件给我:Calriones@hotmail.com

文本比较算法剖析(1)-如何确定最大匹配率

 

1. 首先,我们假设有两个串left和right,
    left="ABCACADF"
    right="BCXCADFESBABCACA"

    为了直观的分析问题,第一步,我用一个表格来逐个的比较left和right的每个元素:

图中,1 表示left 和 right 的某个元素是匹配的,0, 就是不匹配了, 那么, 现在的问题就是, 如何从表格中的左上角,找到一条路径,满足:
    1. 经过的值为"1"的单元格最多;
    2. 每次只能向右,或者向下,或者向右下方移动一格;
    3. 如果本次位置在值为"1"的格子上,只能向右下方移动一格;
    4. 如果移动到右边界或者下边界外,则终止。

2 .这其实就是一个有条件搜索最大权重路径的问题。但是,这里讲的是文本匹配问题,和图论相比,要简单很多。因为文本是流式的,两个文本之间的所有匹配关系一定是一个很规则的矩阵,这比图论中研究的情况要简单多了。

最先想到的是什么呢?迭代和递归,是不是?别着急,没有那么复杂的,我们来分析一下,再做打算。

我们先用手工标出从每个匹配点出发,一直到边界能够经过的最多匹配点个数,如下图所示:

各位可以自己手工做做,分析数量有限的图形,还是大脑比计算机好使。

3. 我们来分析一下,基本的思路是数学归纳法,呵呵,其实是递归算法的数学原型。

边界上的单元,不用说了,一定是最多只能找到一个匹配点。

而对于表格中的任意一个单元, 我们用 N(l,r) 来表示,对于它,按照上面的规则,它有3个邻接区域 A, B, C.

我们用N(l,r)来表示“将left的第L个元素和right的第R个元素匹 配后,能够获取的最大匹配点数”。这个表述有点难以理解,从前面的“找到一个路径...”的观点出发,我们还可以这么说明N(l,r)的含义:“从第L行 R列的单元格出发,满足所有4个条件的路径上能够经过的值为"1"的单元个数”。

因为N(l,r)的下一步一定是区域A,B,C中的一个,而且,如果(l,r)是一个匹配点,只能选择进入A区域;如果进入B,C,则(l,r)一定不是一个匹配点。因此,我们可以得到:
      
N(l,r) = Max( V(l,r)+N(区域A), N(区域B), N(区域C) ) 。"V(l,r)表示单元(l.r)的值,=0表示单元(l,r)不是一个匹配点,=1表示单元(l,r)是一个匹配点"

而一个区域的最大匹配点数,就是从该区域的入口点出发,所能得到的最大匹配点数,即:N(区域[(a,b),(c,d)]) = N(a,b).  "区域[(a,b),(c,d)]的意思是:由点(a,b) 和点(c,d)所构成的矩形区域)"

那么,前式就变成了:

N(l,r) = Max( V(l.r)+N(区域A), N(区域B), N(区域C) ) 
         = Max( N(l+1,r+1)+V(l,r) , N(l,r+1),  N(l+1,r))

在excel中,我们可以验证一下,设置单元格L4的公式=MAX(L5,M5+B4,M4),然后拷贝这个公式直到和前面的矩阵相匹配,我们得到的结果如下:

可以和手工分析的结果对照一下(上图中最右部分),可以看到,结果完全一致。

Yes! 现在已经接近大功告成拉!简单吧!现在,就是如何代码化的问题了。

要将上面的方法编程,还差一个问题:初始化。这个很简单,从Excel的计算结果我们就可以知道。在上面的单元格公式中,边界单元引用了空白单元,而我们知道excel对空白单元取值做算术运算时是按照0计算的,所以初始化为0就可以了。

 再从上面的分析可以知道:
1. 循环应该是从右向左,从下向上的;
2. 每个单元格的值只需要计算一次;
3. 计算N(l,r)时,需要引用3个值
因此,程序应该做逆序循环,用一个数组缓存N(l+1,r)和N(l+1,r+1)的值,用一个临时变量缓存N(l,r+1).

假设left有M个元素;right有N个元素,那么,这个程序的时间复杂度就是O(m.n), 空间复杂度就是Max(m,n).

好了,关于如何计算left和right的最大匹配数,就结束了。很简单,不是么?

如果想做一个文件比较工具的话,还需要确定最优的匹配路径。这个打算在下次再说,算法也比较简单,不过现在已经11点多了,明天要早起喽! <script src="http://www.csdn.net/ui/scripts/Csdn/counter.js" type="text/javascript"></script> <script src="http://message.csdn.net/msg.popup.js" type="text/javascript"></script> <script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script> <script type="text/javascript"> try { var pageTracker = _gat._getTracker("UA-2688088-9"); pageTracker._trackPageview(); } catch (err) { } </script>

文本比较算法剖析(1)-如何确定最大匹配率 收藏

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页