将缩写与字典匹配的最快方法

时间:2014-01-09 06:36:59

标签: regex algorithm data-structures dictionary abbreviation

缩写是一串字母数字字符。数字表示要跳过的字母数,例如i18n是国际化的缩写。 inter15和20也是如此。假设你有一个单词词典,找到字典中与给定缩写匹配的所有单词的最快方法是什么?您可以将任何数据结构用于字典,但查找匹配单词的算法必须优于O(n),其中n是字典中单词的数量。

3 个答案:

答案 0 :(得分:1)

所以你的查询是prefix - count - suffix。有几种方法可以解决这个问题。

如果前缀永远不会为空,那么您可以构建一个前缀树(它只是一个trie),并查询以该前缀开头的所有单词,过滤那些具有所请求长度和后缀的单词。

您可以通过构建generalized suffix tree来完成同样的事情。

或者,由于前缀或后缀可能为空,因此您可以构建前缀树和后缀树。查询两者,过滤长度,并将结果合并。

您可以设想构建一个前缀后缀树。数据结构比拥有两个单独的树要复杂一些,但它需要更少的内存。

我记得(已经有几年了),你可以使用有向无环字图(DAWG)完成所有这些以及更多(搜索缺少字母的单词等)。

答案 1 :(得分:0)

解决方案是对多个数组中的所有单词进行分类。每个数组都包含具有特定字母数量的所有单词。 例如,一个包含4个字母的数组,如:食物,木头,像,梭子鱼等。 另有5个字母等等。

因此,在你的缩回i18n中,你将字符和数字分开:“在”“18”中你将字符数量加到数字上:2 + 18 = 20。现在你知道你的单词是20个字母的单词数组。

我认为我们可以做得更好,但这比在整个词典中找一个单词要好。

答案 2 :(得分:0)

这是a10n树的一个想法(缩写树,或者应该是a10n t2e?)。

缺少的字母将由缺失的块的长度替换,因此匹配的长度事先已知。将字典细分为包含恒定长度字的子字典是有意义的:

dict -> dict2 -> {ad, ah, am, an, as, at, ...}
     -> dict3 -> {abe, abo, abu, ace, act, ada, add, ... }
     -> dict4 -> {abba, abbe, abby, ...}
     -> ...

每个词典都包含一个有序的单词列表。如果缩写是,例如“5”,则返回长度为5的子字典的列表。如果缩写为“绿色”,即根本没有缩写,请使用二分查找检查该单词是否在列表中。

在满足琐碎案件的情况下,我们必须找到一种快速搜索此列表的方法。让我们介绍一个位置和字母树。树的第一层指的是字母的位置,第二层指的是字母本身,就像在trie中一样,例如:

dict3 ->  i == 0 -> a   -> {ant}
                 -> b   -> {bat, bee}
                 -> c   -> {cat, cod, cow}
                 -> ...
          i == 1 -> a   -> {bat, cat, rat}
                 -> b   -> {}
                 -> c   -> {}
                 -> ...

现在找到所有给定字母的列表的交集。如果我们正在寻找“c2”,我们将列表放在(0,c)。如果我们正在寻找“b1t”,我们采用(0,b)和(2,t)处的列表的交集。订购列表时,找到交叉点应该相当快。

还有其他方法。尝试是一种数据结构,允许我们快速搜索字典。 我在对一篇现已删除的帖子的评论中说过,在这种情况下,我认为尝试不是一个合适的数据结构,因为当第一个字母已知时,尝试有助于查找单词。但是我现在不太确定:当发现一个通配符,即一个丢失的字母时,可以下降一个特里的所有分支。对于像'i18n'这样的单词,分支的数量似乎相当大,但在实践中,会有很多空分支。在我的(小)测试词中,大约45,000个单词,没有任何词匹配'i18n',甚至没有国际化。因此,对于真实的词典,尝试甚至可能是一种选择。

(向删除答案的用户道歉,但我在评论中提到了dict的单个trie。如果字典不是庞大的话,每个长度的子测试可能会有用。)