【问题标题】:find a matrix in a big matrix在一个大矩阵中找到一个矩阵
【发布时间】:2013-05-25 14:53:25
【问题描述】:

我有一个非常大的n*m 矩阵S。我想有效地确定S 内部是否存在子矩阵F。大矩阵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%.

【问题讨论】:

  • 在您的示例中,矩阵 [1,3;7,9](即仅角)是否会被视为在 S 内?
  • 不,它必须聚集在一个矩阵中
  • 矩阵应该是连续的、聚集的。

标签: c++ algorithm


【解决方案1】:

它涉及预处理矩阵。这会占用大量内存,但在计算时间方面应该会更好。

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

【讨论】:

    【解决方案2】:

    如果您想多次查询相同的大矩阵和相同大小的子矩阵。预处理大矩阵有很多解决方案。

    这里有一个类似(甚至相同)的问题。

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

    【讨论】:

      【解决方案3】:

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

      Find location of submatrix

      【讨论】:

        【解决方案4】:

        由于您也将问题标记为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;
           }
        } 
        

        【讨论】:

          【解决方案5】:

          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;
             }
          }
          

          【讨论】:

          • 你好,我有一个 Matrix 为 20*20 另一个是 3*3,但是结果是错误的,使用上面的代码。我可以知道代码有什么限制吗?
          • @bob90937 因此我没有测试高阶矩阵,所以我不限制此代码
          【解决方案6】:

          大部分答案取决于您重复执行的操作。您是否正在为同一个子矩阵测试一堆巨大的矩阵?您是否正在测试一个巨大的矩阵来寻找一堆不同的子矩阵?

          是否有任何矩阵具有重复的模式,或者它们是否很好且随机,或者您能否对数据不做任何假设?

          另外,子矩阵是否必须是连续的? S是否包含

          F3 = 1 3
               7 9
          

          【讨论】:

          • 矩阵应该是连续的和收集的,其他信息我已经添加到问题的底部。
          【解决方案7】:

          如果矩阵中的数据不是随机分布的,对它进行一些统计分析会很有帮助。然后,您可以通过比较其逆概率范围内的元素来找到子矩阵。它可能会更快,然后是普通的蛮力。

          说,你有一些正态分布整数的矩阵,高斯中心在 0。你想找到子矩阵说:

          1 3 -12
          -3 43 -1
          198 2 2
          

          您必须开始搜索 198,然后检查右上角的元素为 43,然后检查其右上角的 -12,然​​后任何 3 或 -3 都可以;等等。与最残酷的解决方案相比,这将大大减少比较次数。

          【讨论】:

            【解决方案8】:

            我原来的答案在break下面,想想有几个优化,这些优化参考了原来答案的步骤。

            对于步骤 B),不要搜索整个 S:您可以忽略不适合 F 的所有列和行。 (在下面的例子中,只搜索左上角的 2x2 矩阵)。如果FS 的很大一部分,这将节省大量时间。

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


            使用这两个矩阵

            在里面找到

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

            B) 在较大的范围内定位它

            C) 检查相邻单元格是否匹配

            -

            【讨论】:

            • 他正在处理一个 500*500 的矩阵。
            【解决方案9】:

            可以在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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2022-11-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-03-27
              • 2016-12-21
              相关资源
              最近更新 更多