java – 部分匹配长度的正则表达式 – 字符串相似度

说我有字符串“Torcellite”和另一个字符串“Tor” – 这两个字符串的相似长度是3,因为它们都以“Tor”开头.现在,另一个字符串“christmas”和“mas”将具有0的相似度,因为它们不以相同的字符集开头.

在这两种情况下,第二个字符串是第一个字符串的后缀.

一个更清晰的例子:

字符串长度:1〜10 ^ 5

String:abaabc

后缀:abaabc,baabc,aabc,abc,bc,c

相似度:abaabc,none,a,ab,none,none

相似长度:6,0,1,2,0,0

答:6 0 1 2 0 0 = 9

我有一个无效的逻辑来找到这些部分后缀匹配使用正则表达式.

算法:

>查找给定字符串的所有子字符串.
>从后缀的子字符串中创建一个模式.

for(int i=1; i<substrings[i].length; i++) {
    Pattern p = Pattern.compile("^"+substrings[i].substring(0, i));
    Matcher m = p.find(string); //the given string for which similarities need to be  calculated
    if(m.find())
        similaryLengths +=  i;
}

>因为我需要运行字符串的后缀,然后是模式的子字符串,所以它的复杂度大致为O(n ^ 2).
>我想到在模式中使用分组来查找组,但我不确定正则表达式将是什么样子.我想到的是第一个子串是:(((((a)b)a)a)b)c)然后找到最长的组匹配.

有没有更有效的算法可以实现他?

最佳答案
到目前为止,最好的方法是在输入字符串上构建一个后缀树.构建后缀树只需要O(n)个时间,其中n是字符串的长度.后缀树在逻辑上由一棵树组成,其中可以通过从根到每个叶的步行找到字符串的所有后缀.您可以使用read Wikipedia了解这些树如何工作的更多细节.

本质上,后缀树将允许您简单地将您当前的问题重写为“查找”后缀树中的原始字符串之一.当您沿树下走时,您可以计算每个子树中的后缀数,并乘以当前匹配长度来确定您的分数.这个“搜索”也是O(n)时间.

所以最终的结果是可以用O(n)的预处理时间解决保证的O(n)时间和O(n)空间的问题.这是非常有效率的!而且,没有产生二次行为的“最坏情况”.你可以很容易地处理长达10 ^ 7的字符串.

实现的唯一困难将是构建后缀树,但是可以找到免费的代码.

转载注明原文:java – 部分匹配长度的正则表达式 – 字符串相似度 - 代码日志