在大矩阵中找到矩阵

时间:2013-05-25 14:53:25

标签: c++ algorithm

我有一个非常大的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%.

9 个答案:

答案 0 :(得分:1)

如果要多次查询同一个大矩阵和相同大小的子矩阵。有许多解决方案可以预处理大矩阵。

此处存在类似(甚至相同)的问题。

Fastest way to Find a m x n submatrix in M X N matrix

答案 1 :(得分:1)

它涉及预处理矩阵。这对内存很重,但就计算时间而言应该更好。

  • 在检查前检查子矩阵的大小是否小于矩阵的大小。
  • 构建矩阵时,构建一个构造,将矩阵中的值映射到矩阵中的(x,y)位置数组。这将允许您检查候选可能存在的子矩阵的存在。您将在子矩阵中使用(0,0)处的值,并在较大的矩阵中获取此值的可能位置。如果位置列表为空,则表示没有候选项,因此子矩阵不存在。有一个开始(更有经验的人可能认为这是一种天真的方法)。

答案 2 :(得分:1)

因为您只想知道给定矩阵是否在另一个大矩阵内。如果您知道如何使用C ++中的Matlab代码,则可以直接使用Matlab中的ismember。另一种方法可能是尝试弄清楚成员如何在Matlab中工作,然后在C ++中实现相同的东西。

请参阅Find location of submatrix

答案 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矩阵)。如果FS的很大一部分,则可以节省大量时间。

如果S内的值范围非常低,那么创建查找表将大大减少步骤B)所需的时间。


使用这两个矩阵

mat2

中找到mat1

A)从较小的矩阵中选择一个值:

mat4

B)将其放在较大的

mat3

C)检查相邻的单元格以查看它们是否匹配

mat6 - mat5

答案 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