字符串相似度算法完全指南:编辑、令牌与序列三类算法的全面解析与深入分析-基于序列的算法

时间:2024-07-10 07:00:12

基于序列的算法更侧重于分析和比较整个序列,而不是像基于令牌的算法那样比较序列中的令牌。这些算法在处理DNA序列、蛋白质序列或自然语言句子时尤其有价值。这里有一些示例性的例子:

1、Ratcliff-Obershelp相似度

Ratcliff-Obershelp相似度或Gestalt模式匹配是一种字符串相似度测量方法,侧重于基于两个字符串之间的共同子字符串来找到相似性。它特别适用于比较具有相似结构但可能在细微修改、删除或插入方面有所不同的字符串。该算法根据两个字符串之间最长公共子字符串的长度分配相似度分数。

Ratcliff-Obershelp算法的工作方式如下:

找到最长公共子字符串(LCS),在两个输入字符串之间识别最长的公共子字符串。这是通过找到在两个字符串中以相同顺序出现的公共字符序列来完成的。

然后首先移除LCS部分,并在同一位置进行分割。这将字符串分割成两部分:一部分在公共部分的左边,另一部分在右边。然后取两个字符串的左部分,再次应用此过程以找到它们的LCS。同样的过程也适用于右部分。继续递归这个过程,直到任何分割部分小于一定的设定值。

最后使用前面提到的Sorensen-Dice公式计算相似度分数。这个分数是共享字符数的两倍,除以两个字符串中的总字符数。

下面通过比较“RO pattern matching”和“RO practice”来清晰地解释这个算法。

共同的子字符串是“RO p”(4个字符)、‘a’(1个字符)、‘t’(1个字符)、‘e’(1个字符)。这意味着相似度为2*(4+1+1+1)/(19 + 11)=0.467。

但是这个算法有两个致命的缺点,第一个是它的复杂性,为O(n³),另一个是该算法不是可交换的,这意味着D(X, Y) != D(Y, X)。

对于第二个问题,我们来验证一下,第一个例子我们有D(“RO pattern matching”, “RO practice”)。让我们计算另一种方式:

 >> s1, s2 = "RO PATTERN MATCHING", "RO PRACTICE"
 >> td.ratcliff_obershelp(s1, s2), td.ratcliff_obershelp(s2, s1), len(s1), len(s2)
 (0.46, 0.53, 19, 11)

共同的子字符串是“RO p”(4个字符)、‘r’(1个字符)、‘a’(1个字符)、‘c’(1个字符)、‘i’(1个字符)。这意味着相似度为2*(4+1+1+1+1)/(19 + 11)=0.53。

这个例子展示了Ratcliff-Obershelp算法不可交换性的特点,即从不同的方向比较相同的字符串对可能得到不同的相似度分数。这一性质在需要对称相似度的应用中可能是一个限制。

2、最长公共子字符串/子序列相似度

最长公共子字符串算法是一种字符串相似度算法,专注于找出两个字符串之间的最长公共子字符串。它通过识别两个字符串共享的最长连续字符序列来衡量字符串之间的相似度。相似度得分可以通过将最长公共子字符串的长度除以最长字符串的长度来计算。

与子字符串不同,子序列不要求在原始序列中占据连续位置。因此,最长公共子序列总是大于最长公共子字符串。相似度得分的计算方式与后者相同。

以下示例:

 >> s1, s2 = "RO PATTERN MATCHING", "RO PRACTICE"
 >> td.lcsstr(s1, s2), td.lcsseq(s2, s1), td.lcsseq(s2, s1)
 ('RO P', 'RO PRATC', 'RO PRACI')
 >> td.lcsstr.normalized_similarity(s1, s2), td.lcsseq.normalized_similarity(s1, s2)
 (0.21, 0.42)

在上述示例中可以看到最长公共子字符串总是具有连续字符的子字符串,但在最长公共子序列中没有这个约束。

(A, B)的最长公共子序列与(B, A)不同。实际上可以在上面的例子中看到不同的结果(RO PRATC)和(RO PRACI)。