如何实现滑动窗口或减少这些嵌套循环?

时间:2019-11-22 22:08:03

标签: java algorithm loops optimization

我正在尝试减少这些循环以优化一些代码。有人建议我使用滑动窗口技术,但似乎无法使其适合我的示例。

我在括号中添加的所有内容只是为了表明它们是什么类型。 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语句或某些要查找的集合替换内部循环与嵌套循环本质上相同,因此不会执行。我一直无法实现滑动窗口(不确定是否可以实现)。

我一直在这里陷入困境,不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

这是字符串搜索问题。

有一种有效的滑动窗口技术,称为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)的速度很慢。

您可能想改用BufferedInputStream(FileInputStream(...))。这样可以一次给您一个字节。使用符合此限制的字符串搜索。最好使用Knuth-Morris-Pratt,或者如果字符串确实限于8个字节,那么整个字符串就可以放入long中。使用它可以将文件中的所有8个字符与前8个字符直接进行比较,其中一个字符==