DP Matching算法
摘要:文章:DP Matching算法 摘要:DPMatching算法常用于比较两组数据,两组数据中数据的个数可以不一样。例如:比较声音A与声音B更像一些,还是声音A,发表于北京联高软件有限公司技术文章栏目,代码以高亮显示。
关键字:matching, dp, 算法, br, td, center, align, tr, div, table, 字符, 距离, 短路, 数据, border, 声音
DP Matching算法常用于比较两组数据,两组数据中数据的个数可以不一样。例如:比较声音A与声音B更像一些,还是声音A与声音C更像一些。
下面我们简单介绍一下该算法的原理。以比较两个长度不相同的字符串为例。
用DP Matching算法比较字符串解释:
假设有两个字符串s: waseda 和t: weasida ,
首先可以做成一张表格d:
* | w | a | s | e | d | a |
w | 1 | 3 | 3 | 3 | 3 | 3 |
e | 3 | 3 | 3 | 1 | 3 | 3 |
a | 3 | 1 | 3 | 3 | 3 | 1 |
s | 3 | 3 | 1 | 3 | 3 | 3 |
i | 3 | 3 | 3 | 3 | 3 | 3 |
d | 3 | 3 | 3 | 3 | 1 | 3 |
a | 3 | 1 | 3 | 3 | 3 | 1 |
上面的表格的做法是,如果s[i]=t[j],那么d[i][j]=1,否则d[i][j]=3;
我们可以称最左上角的d[0][0](带有‘*’号那个点)再往左上的那个点(实际上这个点在表中是不存在的)是原点
然后求各点到原点的最短距离。并且要求这个最短路径的前进方向只能是从左至右,或从上至下,或从左上至右下。也就是说,不可以往回拐。必须是从原点一直奔右下角去的。
我们可以根据d表再做一张g表,用来存放d表中各点到原点的最短距离:做法如下:
1.这个表最左上的点的距离,当然就是d[0][0]的值了。亦即:g[0][0]=d[0][0];
* | w | a | s | e | d | a |
w | 1 | ? | ? | ? | ? | ? |
e | ? | ? | ? | ? | ? | ? |
a | ? | ? | ? | ? | ? | ? |
s | ? | ? | ? | ? | ? | ? |
i | ? | ? | ? | ? | ? | ? |
d | ? | ? | ? | ? | ? | ? |
a | ? | ? | ? | ? | ? | ? |
2.接下去也好办。这个表中第一行和第一列的值也可以求出来。第一行的点g[i][0]值,不用说,肯定是这个点在d表中的值(d[i][0])加上这个点左边的那个点在g表中的值(g[i-1][0])。从g[[1][0]开始算,
g[1][0]=d[1][0]+g[0][0];
g[2][0]=d[2][0]+g[1][0];
g[3][0]=d[3][0]+g[2][0];
... ...
第一列亦然
g[0][1]=d[0][1]+g[0][0];
g[0][2]=d[0][2]+g[0][1];
g[0][3]=d[0][3]+g[0][2];
... ...
* | w | a | s | e | d | a |
w | 1 | 4 | 7 | 10 | 13 | 16 |
e | 4 | ? | ? | ? | ? | ? |
a | 7 | ? | ? | ? | ? | ? |
s | 10 | ? | ? | ? | ? | ? |
i | 13 | ? | ? | ? | ? | ? |
d | 16 | ? | ? | ? | ? | ? |
a | 19 | ? | ? | ? | ? | ? |
3.然后算剩下的点。那么剩下的每个点应该是这个点在d表中的值加上它左上,左,上这三个点中在g表中的值最小的那个点,也就是说:
g[i][j] = d[i][j] + min( g[i-1][j-1], g[i-1][j], g[i][j-1]) ;
* | w | a | s | e | d | a |
w | 1 | 4 | 7 | 10 | 13 | 16 |
e | 4 | 4 | 7 | 8 | 11 | 14 |
a | 7 | 5 | 7 | 10 | 11 | 12 |
s | 10 | 8 | 6 | 9 | 12 | 14 |
i | 13 | 11 | 9 | 9 | 12 | 15 |
d | 16 | 14 | 12 | 12 | 10 | 13 |
a | 19 | 15 | 15 | 15 | 13 | 11 |
g表也做出来了。从右下角开始,找出到左上角的最短距离来,方法也很简单。我们已经说好了从左上角到右下角的最短路径的前进方向一定是从左到右,或者从上到下,或者从左上到右下,那反过来的路径的前进方向一定是从右到左,或者从下到上,或者从右下到左上。从最右下点(在这里是g[5][6]==11)开始。
左上,左,上,这三个点里哪个值最小?是左上的g[4][5]==10吧?
再来,下一个呢?也是左上的g[3][4]==9吧?
继续,左上的g[2][3]==6,g[1][2]==5
然后有麻烦了。g[1][2]这个点挺气人。他左上和上都是4,TMD。咱们选上边g[1][1]的吧。然后到左上角g[0][0]了。
这样从左上到右下的最短距离就找出来了。
g[0][0] , g[1][1], g[1][2], g[2][3] , g[3][4], g[4][5], g[5][6]
说了这么半天,这和比较字符串有什么关系?先别着急拍板砖。我们看一下这个最短路径:基本上都是从左上至右下的。其实这正是我们所希望的方向。想一想:如果有某个点(i,j),如果在最短路径中这个点的前进方向是右下,也就是说,它的下一个点是(i+1,j+1),那么是不是可以理解成为:这个点所对应的两个符串中的两个字符是一样的。
对于点(i,j),如果下一个点是(i+1,j+1),则应该有s[i]==t[j]。(s和t是那两个字符串)
要不,就可能是这个点应该是一个置换。
我们还可以自己试试定义一下。如果往左走的话是脱落D,如果往下走的话是插入I
写个程序验证一下(^_^)
如上所述。比较两个字符串,只是DP Matching简单的应用。关于DP
Matching算法在语音比较、画像比较等多媒体数据处理方面的应用。我会在日后翻译一些资料。