【问题标题】:Best way to check if a byte[] is contained in another byte[] [duplicate]检查一个字节[]是否包含在另一个字节[]中的最佳方法[重复]
【发布时间】:2011-07-01 00:52:31
【问题描述】:

可能重复:
byte[] array pattern search

你好,

如果一个字节[]在另一个字节[]中,最好的搜索方法是什么。

例如

byte[] first = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };
byte[] second = new byte[] { 0x01, 0x02 };
byte[] third = new byte[] { 0x01, 0x03 };

该方法将返回:

first.Contains(second); // true
first.Contains(third); // false
second.Contains(third); // false

谢谢!

【问题讨论】:

  • 您是否在寻求比您所展示的更好的方法?
  • 我展示的,只搜索数组中的一个字节。匹配序列中需要多个字节。
  • 请注意,这是要求任何匹配,而原始要求是多重匹配

标签: c# .net-4.0


【解决方案1】:

您可以使用 Jb 的 Locate method 并在第一场比赛中尽早出局

例如:

static class ByteArrayRocks
{

    public static bool Contains(this byte[] self, byte[] candidate)
    {
        if (IsEmptyLocate(self, candidate))
            return false;

        for (int i = 0; i < self.Length; i++)
        {
            if (IsMatch(self, i, candidate))
                return true;
        }

        return false;
    }

    static bool IsMatch(byte[] array, int position, byte[] candidate)
    {
        if (candidate.Length > (array.Length - position))
            return false;

        for (int i = 0; i < candidate.Length; i++)
            if (array[position + i] != candidate[i])
                return false;

        return true;
    }

    static bool IsEmptyLocate(byte[] array, byte[] candidate)
    {
        return array == null
                || candidate == null
                || array.Length == 0
                || candidate.Length == 0
                || candidate.Length > array.Length;
    }
}

class Program
{
    static void Main()
    {
        var data = new byte[] { 23, 36, 43, 76, 125, 56, 34, 234, 12, 3, 5, 76, 8, 0, 6, 125, 234, 56, 211, 122, 22, 4, 7, 89, 76, 64, 12, 3, 5, 76, 8, 0, 6, 125 };
        var pattern = new byte[] { 12, 3, 5, 76, 8, 0, 6, 125,11 };

        Console.WriteLine(data.Contains(pattern));


        Console.ReadKey();
    }
}

对于某些数组,这将比Boyer-Moore 效率低得多,因为如果存在不匹配,它能够更快地跳过数组。除了许多其他算法here,还有 C# 实现。

这是使用它和 horspool 的维基百科实现的改编。

static class Horspool
{
    private static int[] BuildBadSkipArray(byte[] needle)
    {
        const int MAX_SIZE = 256;

        int[] skip = new int[MAX_SIZE];
        var needleLength = needle.Length;

        for (int c = 0; c < MAX_SIZE; c += 1)
        {
            skip[c] = needleLength;
        }

        var last = needleLength - 1;

        for (int scan = 0; scan < last; scan++)
        {
            skip[needle[scan]] = last - scan;
        }

        return skip;
    }

    public static bool ContainsHorspool(this byte[] haystack, byte[] needle)
    {
        var hlen = haystack.Length;
        var nlen = needle.Length;
        var badCharSkip = BuildBadSkipArray(needle);
        var last = nlen - 1;

        int offset = 0;
        int scan = nlen;

        while (offset + last < hlen)
        {

            for (scan = last; haystack[scan + offset] == needle[scan]; scan = scan - 1)
            {
                if (scan == 0)
                {
                    return true;
                }
            }

            offset += badCharSkip[haystack[scan + offset]];

        }

        return false;
    }
}

【讨论】:

  • +1 推荐 Boyer-Moore。任何字符串搜索算法都应该适用于此。
  • 上面的第二个列表对我不起作用,结果是一个错字。 offset+= line 应该读过 offset += badCharSkip[haystack[last + offset]];
猜你喜欢
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
相关资源
最近更新 更多