如何加快搜索前导通配符匹配的按字母顺序排列的单词列表

How to speed up searching alphabetized word list for leading wildcard matches

我在业余时间是个字谜迷,所以我花了很多其他业余时间来开发一个允许在搜索模式中使用通配符的帮助程序。它很好用。在我的戴尔笔记本电脑(i5、8GB RAM)上搜索 140,000 个单词 "dictionary" 以进行通配符匹配时,只有数万个单词 return编辑。 Java 规则。 regexmatch() 的实现也是如此。

我希望将它移植到 Android。我整天都在努力编译一个或多或少等效的应用程序。给定的代码架构没有机会。

问题是可以(必须)允许使用前导通配符。例如,???ENE returns 15 个匹配项——从 achENExylENE*RAT returns 22 个匹配项——从 aristocRAT 通过`zikuRAT——也就是说,必须(?)搜索所有 140,000 个单词,这将在大多数(全部?)Android 设备上花费 aaaaaaaaawhiiiiiiiile。 (每个在我的笔记本电脑上花费的时间不到一秒。)(我的 PC 需要 3 秒才能 return 所有 140,000 个单词,并且需要更长的时间来观察所有单词。)

由于某些单词拼图允许单词中的字母数量可变,因此禁止使用前导通配符会消除此类谜题的应用程序的核心。但是,如果搜索模式必须以字母开头,那么进行二分搜索(或更快的搜索)就足够容易了。 (而且它仍然可能慢得令人无法接受。)

无论如何,我想知道是否有人可能知道一些算法或可以想到一些可用于加速使用前导通配符进行搜索的方法。

我相信您尝试做的优化版本被广泛称为 Unix/Linux 实用程序 "grep",如果我没记错的话,它使用 Boyer-Moore 搜索算法。

在幕后,Java 的模式 class 使用 Boyer-Moore。而且它支持正则表达式,所以如果你能写一些东西把你的通配符搜索模式变成正则表达式,你可以使用 Pattern。

http://www.java2s.com/Code/Java/Regular-Expressions/AnotherGrep.htm

有一个有趣的 Java grep 实现

它使用内存映射文件。我猜你无法将整个单词列表放入内存中,但你可以将它拆分成一堆较小的文件——上面的实现一次一次映射一个文件。您必须进行一些测试才能找到文件的最佳大小。

我刚刚用谷歌搜索,发现第二个列表按字母顺序反向排列可能是一种让前导通配符变为尾随的方法,为模式开始的二进制搜索打开了大门。有趣的。但是*a???ene*也是程序中合法的搜索模式。然后怎样呢? (是的。您需要多久进行一次此类搜索。)

我刚找到关于 Apache Lucene 的:

Leading wildcards (e.g. *ook) are not supported by the QueryParser by default. 从 Lucene 2.1 开始,可以通过调用 QueryParser.setAllowLeadingWildcard( true ) 来启用它们。请注意,这可能是一项代价高昂的操作:它需要完整地扫描索引中的标记列表以查找与模式匹配的标记。