我的业余时间里有一个单词拼图,所以我花了很多其他的空余时间来处理一个帮助程序,它允许搜索模式中的通配符。它很棒。在我的戴尔笔记本电脑(i5,8GB RAM)上搜索一个14万字的字典"对于单词的通配符匹配具有几乎难以察觉且绝对可接受的延迟,只有在返回数万个单词时才会发生。 Java规则。 regex
和match()
的实施也是如此。
我希望将它移植到Android。我整天都在努力获得一个或多或少等同的应用程序来编译。没有给定代码架构的机会。
问题是可以(必须)允许使用前导通配符。例如,???ENE
返回15个匹配项 - 从achENE
到xylENE
,*RAT
返回22个匹配项 - 从aristocRAT
到zikuRAT - 即所有140,000必须(?)搜索单词,这将在大多数(所有?)Android设备上采用aaaaaaaaawhiiiiiiii。 (每次在我的笔记本电脑上花费的时间不到一秒钟。)(我的电脑需要3秒钟才能返回所有140,000个单词并且需要更长时间才能全部注视它们。)
由于某些单词拼图允许在单词中使用可变数量的字母,因此禁止使用领先的通配符可以减少应用程序对这些拼图的影响。但是如果搜索模式必须以字母开头,那么就可以很容易地进行二分搜索(或者更快的搜索)。 (它仍然可能慢得令人无法接受。)
无论如何,我想知道是否有人可能知道一些算法,或者可以想到一些可能用于加速使用前导通配符搜索的方法。
答案 0 :(得分:1)
我相信您尝试做的优化版本被广泛称为Unix / Linux实用程序“grep”,如果我没记错的话,使用Boyer-Moore搜索算法。
在幕后,Java的Pattern类使用Boyer-Moore。并且它支持正则表达式,因此如果您可以编写一些内容来将通配符搜索模式转换为正则表达式,则可以使用Pattern。
http://www.java2s.com/Code/Java/Regular-Expressions/AnotherGrep.htm
有一个有趣的grep Java实现它使用内存映射文件。我猜你将无法将整个单词列表放入内存中,但是你可以将它分成一堆较小的文件 - 上面的内存实现 - 一次映射一个文件。您必须进行一些测试才能找到文件的最佳大小。
答案 1 :(得分:0)
我只是谷歌搜索并发现有一个反向按字母顺序排列的第二个列表可能是一种方式,然后有一个领先的通配符变为尾随,打开二进制搜索模式开始的大门。有趣。但*a???ene*
也是该计划中的合法搜索模式。然后怎样呢? (是的。你多久需要这样的搜索。)
我刚刚发现了关于Apache Lucene:
Leading wildcards (e.g. *ook) are not supported by the QueryParser by default.
从Lucene 2.1开始,可以通过调用QueryParser.setAllowLeadingWildcard( true )
启用它们。请注意,这可能是一项昂贵的操作:它需要完整地扫描索引中的标记列表,以查找与模式匹配的标记。