在 M X N 矩阵中找到 m x n 子矩阵的最快方法
Fastest way to Find a m x n submatrix in M X N matrix
我在想一种快速的方法,在更大的mtrix M中寻找子矩阵m。我还需要识别部分匹配。
我能想到的几种方法是:
- 优化普通暴力破解,仅处理增量行和列。
- 可以将拉宾-卡普算法扩展到 2-d,但不确定如何处理部分匹配。
我相信这是图像处理中经常遇到的问题,如果有人可以倾注他们的意见或向我指出有关此主题的资源/论文,我将不胜感激。
编辑:较小的示例:
更大的矩阵:
1 2 3 4 5
4 5 6 7 8
9 7 6 5 2
更小的矩阵:
7 8
5 2
结果:(行:1 列:3(
在 (1, 3( 处限定为部分匹配的较小矩阵的示例:
7 9
5 2
如果超过一半的像素匹配,则将其视为部分匹配。
谢谢。
我建议在互联网上搜索"2D模式匹配算法"。你会得到很多结果。我将只链接谷歌上的第一个命中,这篇论文为您的问题提供了一种算法。
您还可以查看论文末尾的引文,以了解其他现有算法。
摘要:
提出了一种在二维n x n文本中搜索二维m x m模式的算法。它执行的比较平均少于文本的大小:n^2/m使用m^2额外空间。基本上,它只在文本的 n/m 行上使用多个字符串匹配。它最多运行 2n^2 次,并且接近许多模式的最佳 n^2 时间。它稳步扩展到具有类似最坏情况的独立于字母的算法。实验结果包含在实际版本中。
如果您愿意预处理矩阵并且对同一矩阵有很多查询,则有非常快速的算法。
看看多媒体数据库研究小组(波恩大学克劳森教授(关于代数数据库的论文。例如,看看这篇论文:http://www-mmdb.iai.uni-bonn.de/download/publications/sigir-03.pdf
基本思想是推广倒排列表,因此他们使用任何类型的代数变换,而不是像普通倒排列表那样只向一个方向移动。
这意味着只要需要对输入数据进行的修改可以代数建模,这种方法就有效。特别是,可以检索以任意数量的维度,旋转,翻转等方式转换的查询。
这篇论文主要针对音乐数据展示这一点,因为这是他们的主要研究兴趣,但你也许可以找到其他人,它们展示了如何将其适应图像数据(或者你可以尝试自己改编,如果你理解原理,它很简单(。
编辑:
如果您正确定义部分匹配,则此想法也适用于部分匹配。
如果您只需要将一个小矩阵与一个大矩阵匹配,则无法快速完成此操作。但是,如果您需要针对大矩阵执行许多小矩阵,则对大矩阵进行预处理。
一个简单的例子,精确匹配,许多 3x3 矩阵对一个巨大的矩阵。
创建一个新的"匹配矩阵",与"大矩阵"大小相同,对于大矩阵中的每个位置,为大矩阵中的每个 x,y 到 x+3,y+3 计算一个 3x3 哈希。现在,您只需扫描匹配矩阵以查找匹配的哈希值。
您可以使用专用哈希函数实现部分匹配,这些函数为具有相同部分匹配属性的事物提供相同的哈希。棘手。
如果要进一步加快速度并为其提供内存,请为匹配矩阵创建哈希表,并在哈希表中查找哈希。
3x3解决方案适用于任何 3x3 或更大的测试矩阵。你不需要有一个完美的哈希方法 - 你只需要一些可以拒绝大多数错误匹配的方法,然后对哈希表中的潜在匹配项进行完全匹配。
我认为你不能用一些方法猜测子矩阵在哪里,但你可以优化你的搜索。
例如,给定一个矩阵 A MxN 和一个子矩阵 B mxn,您可以执行以下操作:
SearchSubMatrix (Matrix A, Matrix B)
answer = (-1, -1)
Loop1:
for i = 0 ... (M-m-1)
|
| for j = 0 ... (N-n-1)
| |
| | bool found = true
| |
| | if A[i][j] = B[0][0] then
| | |
| | | Loop2:
| | | for r = 0 ... (m-1)
| | | | for s = 0 ... (n-1)
| | | | | if B[r][s] != A[r+i][s+j] then
| | | | | | found = false
| | | | | | break Loop2
| |
| | if found then
| | | answer = (i, j)
| | | break Loop1
|
return answer
这样做,您将减少子矩阵大小原因的搜索。
Matrix Submatrix Worst Case:
1 2 3 4 2 4 [1][2][3] 4
4 3 2 1 3 2 [4][3][2] 1
1 3 2 4 [1][3]{2 4}
4 1 3 2 4 1 {3 2}
(M-m+1)(N-n+1) = (4-2+1)(4-2+1) = 9
虽然这是O(M*N)
,但它永远不会看M*N
次,除非你的子矩阵只有一维。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 初始化具有非默认构造函数的std::数组项的更好方法