我有一个非常大的n*m
矩阵S
。我想有效地确定F
内是否存在子矩阵S
。大矩阵S
的大小可以与500*500
一样大。
澄清一下,请考虑以下事项:
S = 1 2 3
4 5 6
7 8 9
F1 = 2 3
5 6
F2 = 1 2
4 6
在这种情况下:
F1
位于S
F2
不在S
矩阵中的每个元素都是32-bit
整数。我只能想到使用蛮力方法来查找F
是否是S
的子矩阵。我用谷歌搜索找到一个有效的算法,但我找不到任何东西。
是否有一些算法或原则可以更快地完成? (或者可能是一些优化蛮力方法的方法?)
PS统计数据
A total of 8 S
On average, each S will be matched against about 44 F.
The probability of success match (i.e. F appears in a S) is
19%.
答案 0 :(得分:1)
如果要多次查询同一个大矩阵和相同大小的子矩阵。有许多解决方案可以预处理大矩阵。
此处存在类似(甚至相同)的问题。
答案 1 :(得分:1)
它涉及预处理矩阵。这对内存很重,但就计算时间而言应该更好。
答案 2 :(得分:1)
因为您只想知道给定矩阵是否在另一个大矩阵内。如果您知道如何使用C ++中的Matlab代码,则可以直接使用Matlab中的ismember
。另一种方法可能是尝试弄清楚成员如何在Matlab中工作,然后在C ++中实现相同的东西。
答案 3 :(得分:1)
由于您已将问题标记为C++
,因此我提供此代码。这是一种强力技术,绝对不是解决这个问题的理想方案。对于S X T
主矩阵和M X N
子矩阵,算法的时间复杂度为O(STMN)
。
cout<<"\nEnter the order of the Main Matrix";
cin>>S>>T;
cout<<"\nEnter the order of the Sub Matrix";
cin>>M>>N;
// Read the Main Matrix into MAT[S][T]
// Read the Sub Matrix into SUB[M][N]
for(i=0; i<(S-M); i++)
{
for(j=0; j<(T-N); j++)
{
flag=0;
for(p=0; p<M; p++)
{
for(q=0; q<N; q++)
{
if(MAT[i+p][j+q] != SUB[p][q])
{
flag=1;
break;
}
}
if(flag==0)
{
cout<<"Match Found in the Main Matrix at starting location "<<(i+1) <<"X"<<(j+1);
break;
}
}
if(flag==0)
{
break;
}
}
if(flag==0)
{
break;
}
}
答案 4 :(得分:1)
Deepu-benson的修改代码
int Ma[][5]= {
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
{0, 1, 0, 0, 0},
{0, 1, 0, 0, 0},
{1, 1, 1, 1, 0}
};
int Su[][3]= {
{1, 0, 0},
{1, 0, 0},
};
int S = 5;// Size of main matrix row
int T = 5;//Size of main matrix column
int M = 2; // size of desire matrix row
int N = 3; // Size of desire matrix column
int flag, i,j,p,q;
for(i=0; i<=(S-M); i++)
{
for(j=0; j<=(T-N); j++)
{
flag=0;
for(p=0; p<M; p++)
{
for(int q=0; q<N; q++)
{
if(Ma[i+p][j+q] != Su[p][q])
{
flag=1;
break;
}
}
}
if(flag==0)
{
printf("Match Found in the Main Matrix at starting location %d, %d",(i+1) ,(j+1));
break;
}
}
if(flag==0)
{
printf("Match Found in the Main Matrix at starting location %d, %d",(i+1) ,(j+1));
break;
}
}
答案 5 :(得分:0)
我的原始答案是在休息之下,考虑到它有几个优化,这些优化是指原始答案的步骤。
对于步骤B),不要搜索整个S
:您可以折扣不允许F
适合的所有列和行。 (在下面的例子中,只搜索左上角的2x2矩阵)。如果F
占S
的很大一部分,则可以节省大量时间。
如果S
内的值范围非常低,那么创建查找表将大大减少步骤B)所需的时间。
使用这两个矩阵
在
中找到A)从较小的矩阵中选择一个值:
B)将其放在较大的
中
C)检查相邻的单元格以查看它们是否匹配
-
答案 6 :(得分:0)
答案很大程度上取决于你重复做什么。你在为同一个子矩阵测试一堆巨大的矩阵吗?你在测试一个巨大的矩阵,寻找一堆不同的子矩阵吗?
任何矩阵都有重复的模式,或者它们是否漂亮且随机,或者您是否可以对数据做出假设?
此外,子矩阵是否必须连续? S是否包含
F3 = 1 3
7 9
答案 7 :(得分:0)
如果矩阵中的数据不是随机分布的,那么对它进行一些统计分析会很有帮助。然后你可以通过比较其元素的反向概率来找到子矩阵。它可能更快,然后是一个普通的暴力。
说,你有一些正态分布的整数矩阵,高斯中心为0.你想找到子矩阵说:
1 3 -12
-3 43 -1
198 2 2
你必须开始搜索198,然后检查右上角元素为43,然后右上角为-12,然后任何3或-3将执行;等等。与最残酷的解决方案相比,这将大大减少比较次数。
答案 8 :(得分:0)
可以在O(N*M*(logN+logM))
中进行。
平等可以表示为平方差之和为0:
sum[i,j](square(S(n+i,m+j)-F(i,j)))=0
sum[i,j]square(S(n+i,m+j))+sum[i,j](square(F(i,j))-2*sum[i,j](S(n+i,m+j)*F(i,j))=0
第一部分可以计算O(N * M)中的所有(n,m),与平均值相似。
第二部分通常以O(sizeof(F))计算,小于O(N * M)。
第三部分是最有趣的。它的卷积可以使用快速傅立叶变换以O(N * M *(logN + logM))计算:http://en.wikipedia.org/wiki/Convolution#Fast_convolution_algorithms