我需要将一组字符串与另一组字符串进行比较,并找出哪些字符串相似(模糊字符串匹配)。 例如:
{ "A.B. Mann Incorporated", "Mr. Enrique Bellini", "Park Management Systems" }
and
{ "Park", "AB Mann Inc.", "E. Bellini" }
假设从零开始的索引,匹配将是0-1,1-2,2-0。显然,在这种类型的事情上,没有算法是完美的。
我有Levenshtein距离算法的工作实现,但是使用它来从每个集合中找到相似的字符串需要循环遍历两组字符串以进行比较,从而产生O(n ^ 2)算法。即使使用适度大小的设置,这也会慢得令人无法接受。
我还尝试过使用叠瓦和Jaccard系数的clustering algorithm。不幸的是,这也在O(n ^ 2)中运行,即使使用位级优化也会导致速度太慢。
有没有人知道一个更有效的算法(比O(n ^ 2)更快),或者更好的是,一个已经用C#编写的库来完成这个?
答案 0 :(得分:1)
不是对O(N ^ 2)的直接回答,而是对N1算法的评论。
这是样本数据,但一切都很干净。这不是我将使用Levenstien的数据。 Incriminate与Incorporated相比距离更近.E。与Enrique不匹配。
Levenshtein-distance擅长捕捉关键输入错误 它也适合匹配OCR。
如果您有干净的数据,我会选择词干和其他自定义规则
如果你有干净的数据,可以使用Porter stemmer进行C#
E.G.
去掉 。和其他标点符号
删除停用词(the)
干
解析每个列表一次,并为每个唯一的词干分配一个int值
在int上做匹配
仍然是N ^ 2,但现在N1更快了
您可以在单个上限中添加匹配以cap开头的单词获得部分分数
还需要考虑单词数量
两组匹配3的5组应该高于两组10匹配的4
我会为每个短语创建Int hashsets,然后相交并计数。
不确定你能否离开N ^ 2 但我建议你看看N1。
Lucene是一个带短语匹配的库,但它并没有真正设置为批次 创建具有多次使用意图的索引,以便在索引创建时优化索引搜索速度。
答案 1 :(得分:0)
在给定的示例中,至少有一个单词始终匹配。一种可能的方法可以使用多图(一个字典能够存储每个键的多个条目)或Dictionary<TKey,List<TVlaue>>
。第一组中的每个字符串将被分成单个单词。这些单词将用作multimap中的键,整个字符串将存储为值。
现在,您可以将第二组中的字符串拆分为单个字,并对每个字执行O(1)查找,即对所有字进行O(N)查找。这产生第一个原始结果,其中每个匹配包含至少一个匹配的单词。最后,您必须通过应用其他规则(例如搜索缩写或缩写词)来优化此原始结果。
答案 2 :(得分:0)
这个问题,称为“字符串相似性连接”,最近在研究界进行了很多研究。我们在C ++中发布了一个名为Flamingo的源代码包,它实现了这样一种算法http://flamingo.ics.uci.edu/releases/4.1/src/partenum/。如果您的数据集对于单个计算机来说太大,我们在http://asterix.ics.uci.edu/fuzzyjoin/也有基于Hadoop的实现。