【问题标题】:C# Array Subset fetchingC# 数组子集获取
【发布时间】:2010-11-04 11:04:02
【问题描述】:

我有一个字节数组,我想确定这个字节数组的内容是否作为连续序列存在于另一个更大的数组中。最简单的方法是什么?

【问题讨论】:

    标签: c# algorithm bytearray search


    【解决方案1】:

    天真的方法是:

    public static bool IsSubsetOf(byte[] set, byte[] subset) {
        for(int i = 0; i < set.Length && i + subset.Length <= set.Length; ++i)
            if (set.Skip(i).Take(subset.Length).SequenceEqual(subset))
                return true;
        return false;
    }
    

    对于更有效的方法,您可以考虑更高级的字符串匹配算法,例如KMP

    【讨论】:

    • @Michal:O(n*m) 可能被认为效率低下,但如果您担心 Skip and Take,请不要担心。这与一对 for 循环一样有效。正如我所说,如果性能是一个问题,您应该考虑更高级的算法。
    • @Mehrdad - 是的,但 mn 对于二进制数据可能会变得相当大......我知道 Skip() 和 Take() 是通过延迟执行完成的 - 所以它只是 n 组件来自 SequenceEquals 的 O(mn)...
    • 性能将是一个问题,但现在我只想让我的代码正常工作。这应该做得很好......
    • Skip() 实际上无法进行索引跳转。它必须在迭代器i 上调用MoveNext() 次。请参阅msmvps.com/blogs/jon_skeet/archive/2011/01/26/… 了解原因。但是有了“如果你担心性能……做其他事情”的警告,这个答案是合理的。
    【解决方案2】:

    尝试适应一些字符串搜索算法。最快的之一是 Boyer-Moore 。这也很容易。对于二进制数据,Knuth-Morris-Pratt 算法也可能非常有效。

    【讨论】:

      【解决方案3】:

      这是这个答案的 1/1 端口:Searching for a sequence of Bytes in a Binary File with Java

      这样做是一种非常有效的方式:

      public static class KmpSearch {
      
          public static int IndexOf(byte[] data, byte[] pattern) {
              int[] failure = ComputeFailure(pattern);
      
              int j = 0;
              if (data.Length == 0) return -1;
      
              for (int i = 0; i < data.Length; i++) {
                  while (j > 0 && pattern[j] != data[i]) {
                      j = failure[j - 1];
                  }
                  if (pattern[j] == data[i]) { j++; }
                  if (j == pattern.Length) {
                      return i - pattern.Length + 1;
                  }
              }
              return -1;
          }
      
      
          private static int[] ComputeFailure(byte[] pattern) {
              int[] failure = new int[pattern.Length];
      
              int j = 0;
              for (int i = 1; i < pattern.Length; i++) {
                  while (j > 0 && pattern[j] != pattern[i]) {
                      j = failure[j - 1];
                  }
                  if (pattern[j] == pattern[i]) {
                      j++;
                  }
                  failure[i] = j;
              }
      
              return failure;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2010-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-03
        • 2010-12-20
        • 2021-08-25
        • 1970-01-01
        • 2018-05-06
        相关资源
        最近更新 更多