问题描述
|
我的问题是,我有一个大约200,000个单词左右的词典。该文件大小为1.8mbs。我想从用户输入,例如** id,我想显示所有可能的匹配项,其中*可以是字母A-Z。 (例如,女佣等)
我正在寻找一些最有效的方法建议,因为我希望用户能够添加更多具体字母并实时更新单词匹配。
我的想法是尝试使用RegexKitLite,但是我的感觉会非常慢。
感谢您的输入!
编辑:您认为可以使用nspredicates来实现这一目标吗?
解决方法
您可以采取哪些措施来优化搜索性能,很大程度上取决于您希望如何限制使用这些通配符。
确切地说:通配符的特征是什么?
仅前缀通配符(m /.+ foobar /)
仅后缀的通配符(m / foobar。+ /)
原子通配符(
m/./
)
动态通配符(m/.+/
)
仅前缀通配符
使用前缀树或DAWG
仅后缀通配符
使用后缀树或DAWG
原子通配符
大幅减少必须运行的比赛数量的一种方法是:
从单词集合中构建一个BKTree。
只要(并且只要)您的通配符具有固定长度(在您的情况下为1),您就可以简单地在BKTree中查询精确编辑距离为n
的节点,其中n
为通配符的数量。传统的BKTree查询具有方差上限。在您的情况下,您想引入一个附加的下限,将接受方差的范围缩小到恰好是[n,1]
(传统上是[0,n]
)。
您会得到一个与查询词不同的词数组,精确地是2个字符。
对于查询“ 7”,一些可能的匹配为:
void
(2x追加)
laid
(2x追加)
bad
(替换1次,添加1次)
to
(2次替换)
虽然这些还不是您查询的正确匹配项,但是表示您的单词总数中只有很小的一部分。
最后但并非最不重要的一点是,您再次运行这些正则表达式匹配结果,然后返回所有剩余的匹配项。
BKTrees引入了levenshtein距离,这是因为一些空间启发式方法会急剧地(取决于单词集合中的熵)来减少所需的比较/匹配次数。
为了获得更多的优化,您可以使用多个BKTree:
将您的收藏分成子集。一组长度为1
的单词,一组长度为2
,一组为3
,依此类推。然后从每个子集中构建一个BKTree。对于查询“ 7”,您将查询BKTree的长度4(通配符像字符一样计数)。
这适用于通配符被解释为“ 0”。但是,如果将通配符解释为m/.?/
,则需要查询BKTree的长度3和4。
除了BKTrees,您还可以使用GADDAG,它是专门用于拼字样式查找的数据结构(Trie的专业化)。
如果我没记错的话,您的通配符也必须严格解释为m/./
。
动态通配符
现在无法想到比对词集合运行正则表达式更好的解决方案。