我有一个大文本(5MB-500MB)文件和一组几千个模式。对于每个模式,我想获取文件中模式的出现次数。该文本不包含空格,是一个基本的长字母数字字符串。
为此,我尝试使用 Aho-Corasick 算法,特别是 Robert-Bor 的 Java 实现,它确实运行得足够快,但是有一个问题:使用模式计算发射的结果,因为它们的字符串不相等使用notepad++等文本编辑器打开文本文件并计算模式的结果。对我来说重要的是,计数的出现次数将恰好是在文件中找到的模式的次数。因此,我需要找到解决这个问题的方法。
为了实现我的目标,我可以在算法的实现中做出改变吗?也许某种 EmitHandler 可以解决我的问题?我也愿意接受其他建议,例如替换算法/解决方案方法。但是,如果可能的话,我想继续使用 java,并尽可能快地获得结果(例如,发出索引对我来说并不重要)。
编辑:例如,即使是安装文件的以下小文本: File Link和模式:
5b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff55b4e5ff
根据发出计数在文件中出现 150 次,但根据 Notepad++/Ctrl-f 在浏览器中的计数功能仅出现 10 次。
以及同一文本的另一个示例:
f34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0ff34a6e0
根据发射计数出现 99 次,但根据文本编辑器的计数仅出现 10 次。
链接到算法的实现,在这里。我目前基于实现运行的内容:
Trie trie = Trie.builder().addKeywords(wordsMap.keySet())
.build();
Collection<Emit> ls2 = trie.parseText(str);``
for (Emit e: ls2) {
if (!map.containsKey(e.getKeyword()))
map.put(e.getKeyword(),1);
else {
int val = map.get(e.getKeyword());
map.replace(e.getKeyword(),val+1);
}
}
return map;
谢谢!
我还尝试了实现中可用的非重叠选项,但它不符合要求,而且对于我的使用来说也太慢了。