说我有一份名单。不幸的是,有一些重复,但其中哪些是重复的并不明显。
Tom Riddle
Tom M. Riddle
tom riddle
Tom Riddle, PhD.
我正在考虑使用 Levenshtein距离,并且肯定会有其他算法一次比较2个名称。
但是在名单列表中,无论字符串距离算法如何,我总是会生成一个比较输出网格(n^2
)。
如何避免O(n^2)
情况?
答案 0 :(得分:1)
这很难。接受你会犯错误,不要让完美成为善的敌人。
首先删除敬意(先生,夫人,先生,博士,博士,小,Sr)。删除常用的名字(基于名字列表)和首字母,并将所有字符转换为大写。为剩下的东西创建一个签名 - 使用Soundex或类似的东西,或者只是删除所有元音和加倍辅音。按签名排序以将相似的名称组合在一起,然后仅对具有相同签名的名称运行完整比较。这减少了排序的时间复杂度O( n log n )以及每组 k ²) > k 签名。
答案 1 :(得分:1)
其他答案已将此视为抽象字符串问题。如果这就是你所追求的,那么我认为他们给出了很好的建议。我将假设你想要使用关于名称如何工作的具体知识,例如,“Thomas Riddle先生,Esq”和“Riddle,Tom”将匹配“Tom Riddle”,但是“Tom Griddle” “不会。
通常,在这种问题中,您可以定义某种规范化函数,并查找规范化为同一事物的术语。在这种情况下,似乎您的名称的规范表示应该包括名字的小写版本,剥离任何标题,并使用昵称到正式名称映射“取消昵称”(假设你想要“汤姆”和“托马斯”匹配)。这个功能会产生“Tom Riddle” - > {first: "tom", last: "riddle"}
,“谜语,汤姆” - > {first: "tom", last: "riddle"}
,“Tom Riddle,Esq” - > {first: "tom", last: "riddle"}
,等等,但是“Tom Griddle” - > {first: "tom", last: "griddle"}
。
一旦有了name-canonicalization函数,就可以创建一个映射(例如hashmap或BST),它将规范名称与非规范化名称列表相关联。对于每个非规范化名称,在地图中找到与其规范形式对应的列表并将其插入其中。完成后,所有包含多个元素的列表都是重复的。