java - 如何实现滑动窗口或减少这些嵌套循环?
问题描述
我正在尝试减少这些循环以优化一些代码。有人建议我使用滑动窗口技术,但我似乎无法让它适合我的例子。
我添加括号中的所有内容只是为了显示它们是什么类型。file.get(..) 方法从文件中的给定索引返回一个字节。外部循环可以(通常)迭代一个巨大的范围,因为这些文件非常大。asciiCombo 的范围为 2-8 个元素。
这是一个嵌套循环,我不确定如何减少:
for (long i = offsetInBytes; i < (long) file.length; ++i) {
int match = 0;
for (int j = 0; j < (int[]) asciiCombo.length; ++j) {
if (file.get(i + j) == asciiCombo[j]) {
match++;
} else {
break;
}
}
}
用 if 语句或某个要查找的集合替换内部循环与嵌套循环基本相同,因此不会这样做。我一直无法实现滑动窗口(甚至不确定我们可以)。
我在这里遇到了一个卡住的地方,不胜感激。谢谢!
解决方案
这是一个字符串搜索问题。
有一种有效的滑动窗口技术,称为 Rabin-Karp 算法:https ://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
它需要一个“特殊”哈希函数,允许您在滑动窗口前进时快速更新其哈希值。我将“特殊”放在引号中,因为最常见的字符串散列方法——多项式散列——确实有效。
但是,有很多选择。我喜欢 Knuth-Morris-Pratt:https ://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
它会为您正在搜索的字符串计算一个状态机,该状态机允许对文件中的每个字节进行一次检查。
Boyer-Moore 也很受欢迎:https ://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm
但是请注意,根据我对您的代码的了解,以及您要查找的字符串通常只有 2-8 个字节长的声明,我认为您选择的搜索算法不会是问题所在。在我看来,您的实施file.get(index)
速度很慢。
您可能想改用 a BufferedInputStream(FileInputStream(...))
。这将按顺序为您提供一个字节。使用适用于此限制的字符串搜索。Knuth-Morris-Pratt 会很好,或者如果字符串真的被限制为 8 个字节,那么整个事情都适合long
. 使用它直接将所有 8 个字符与文件中的前 8 个字符与一个==
.
推荐阅读
- html - 单击图像时无法实现悬停功能
- xml - 使用 concat 显示元素 XSLT
- pandas - Pandas - 如何进行分组,其中新列是(一列的总和)/(分组的数量)的结果?
- c# - 对简单的 Debug.Log(object) 感到困惑 -> 返回“object”和“NULL”
- c++ - 以数组为参数的模板特化
- opengl - 在 OpenGL 4.6 中没有对我有用的 alpha 混合
- java - Spring Boot 将时间戳转换为 UTC,但是当从数据库中获取时转换为服务器时间
- c - JACK 音频声音在播放时改变
- python - python渲染字符串windows路径
- node.js - GraphQL 模式查询无法识别解析器函数中传递的输入参数