【问题标题】:Fast counting of 2D sub-matrices withing a large, dense 2D matrix?在大而密集的二维矩阵中快速计算二维子矩阵?
【发布时间】:2010-12-30 19:54:36
【问题描述】:

在更大、更密集的矩阵中计算子矩阵的好算法是什么?如果我有单行数据,我可以使用后缀树,但我不确定将后缀树推广到更高的维度是否非常简单或最好的方法。

想法?

我对密集矩阵的第一个元素进行索引并消除全矩阵搜索的幼稚解决方案仅比全矩阵扫描提供了适度的改进。

解决这个问题的最佳方法是什么?

Example:

Input:

Full matrix:
123
212
421

Search matrix:
12  
21  

Output:
2

这个子矩阵在完整矩阵中出现 两次,因此输出为 2。完整矩阵可以是 1000x1000,但是,搜索矩阵最大为 100x100(可变大小),并且我需要连续处理多个搜索矩阵。因此,这个问题的蛮力太低效了,无法满足我对几个矩阵的亚秒级搜索时间。

【问题讨论】:

  • 你的意思是计算唯一个子矩阵吗?
  • 我第二点,你的问题陈述不清楚。 Mebbe,您可以提供一个具有预期输出的小示例。
  • 你想要 all 子矩阵还是只想要那些固定大小的子矩阵,例如在你的例子中是正方形?这是前者的上限:math.ucdavis.edu/~sonya/submatrix.pdf
  • 这完全符合我的输出吗?不,我正在计算一个更大的密集矩阵的唯一子矩阵。
  • 我认为他不是在计算唯一的子矩阵,而是计算给定矩阵作为子矩阵出现在较大矩阵中的实例数 --- 这就是示例的工作原理

标签: java algorithm performance matrix


【解决方案1】:

对于算法课程,我曾经做过一个练习,其中必须稍微扩展 Rabin-Karp 字符串搜索算法,以按照您描述的方式搜索匹配的二维子矩阵。

我认为,如果您花时间理解 Wikipedia 上描述的算法,那么您将很清楚将其扩展到二维的自然方式。本质上,您只需在矩阵上进行几次传递,一次沿着一列爬​​行。有一些小技巧可以使时间复杂度尽可能低,但您可能甚至不需要它们。

在 N×N 矩阵中搜索 M×M 矩阵,这种方法应该会给你一个 O(N²⋅M) 算法。有了技巧,我相信它可以细化到 O(N²)。

【讨论】:

  • 在初步测试中,使用散列机制执行子字符串测试的速度超过 4 倍。希望这足以避免更复杂的搜索算法。
  • 我尝试过 Knuth Morris Pratt 而不是 Rabin-Karp,但我的数据集得到了相似的性能结果。这确实是最快、最简单的方法。
【解决方案2】:

Algorithms and Theory of Computation Handbook 建议什么是 N^2 * log(Alphabet Size) 解决方案。给定要搜索的子矩阵,首先对其行进行重复数据删除。现在请注意,如果您逐行搜索大矩阵,则最多有一个重复数据行可以出现在任何位置。使用 Aho-Corasick 及时搜索 N^2 * log(Alphabet Size) 并在大矩阵中的每个单元格处写下 null 或子矩阵匹配行的标识符。现在再次使用 Aho-Corasick 向下搜索此行匹配矩阵的列,并发出所有行都位于彼此下方的匹配信号。

【讨论】:

    【解决方案3】:

    我没有现成的答案,但这是我将如何开始:

    -- 您想要非常快速的查找,您可以在构建索引结构上花费多少(时间)?当蛮力不够快时,您需要索引。

    -- 你对你没有告诉我们的数据有什么了解?所有矩阵中的所有值都是个位数整数吗?

    -- 如果它们是个位数整数(或任何其他可以表示为单个字符或索引值的值),请考虑线性化您的 2D 结构。一种方法是沿着从右上角到左下角的对角线读取矩阵,并从左上角到右下角扫描。难以用语言解释,但请阅读矩阵:

    1234
    5678
    90ab
    cdef
    

    作为 125369470c8adbef

    (明白了吗?)

    现在,您可以根据速度和空间要求的任何深度为您的超级矩阵编制索引;在我的示例中,键 1253... 指向元素 (1,1),键 abef 指向元素 (3,3)。不确定这是否适合您,您将不得不使用解决方案的参数。选择您最喜欢的存储键值对的方法:散列、列表,或者如果事情变得很糟糕,甚至可以在索引中构建一些索引。

    问候

    标记

    【讨论】:

      【解决方案4】:

      这听起来类似于template matching. 如果有动力,您可能可以使用 FFT 转换您的原始数组并从蛮力搜索中删除日志。 (Nlog(M)) 而不是 (NM)

      【讨论】: