{"id":53,"date":"2020-06-06T08:21:48","date_gmt":"2020-06-06T08:21:48","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=53"},"modified":"2020-06-06T08:21:48","modified_gmt":"2020-06-06T08:21:48","slug":"boyermoore-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/06\/06\/boyermoore-cs\/","title":{"rendered":"BoyerMoore.cs"},"content":{"rendered":"\n<p>Boyer Moore Search Algorithm<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\npublic class BoyerMoore\n{\n    private int[]  _jumpTable;\n    private byte[] _pattern;\n    private int    _patternLength;\n    public BoyerMoore()\n    {\n    }\n    public BoyerMoore(byte[] pattern)\n    {\n        SetPattern(pattern);\n    }\n    public void SetPattern(byte[] pattern)\n    {\n        _pattern       = pattern;\n        _jumpTable     = new int[256];\n        _patternLength = _pattern.Length;\n        for (var index = 0; index &lt; 256; index++)\n            _jumpTable[index] = _patternLength;\n        for (var index = 0; index &lt; _patternLength - 1; index++)\n            _jumpTable[_pattern[index]] = _patternLength - index - 1;\n    }\n    public unsafe int Search(byte[] searchArray, int startIndex = 0)\n    {\n        if (_pattern == null)\n            throw new Exception(\"Pattern has not been set.\");\n        if (_patternLength > searchArray.Length)\n            throw new Exception(\"Search Pattern length exceeds search array length.\");\n        var index                 = startIndex;\n        var limit                 = searchArray.Length - _patternLength;\n        var patternLengthMinusOne = _patternLength     - 1;\n        var Moves                 = 0;\n        fixed (byte* pointerToByteArray = searchArray)\n        {\n            var pointerToByteArrayStartingIndex = pointerToByteArray + startIndex;\n            fixed (byte* pointerToPattern = _pattern)\n            {\n                while (index &lt;= limit)\n                {\n                    var j = patternLengthMinusOne;\n                    while (j >= 0 &amp;&amp; pointerToPattern[j] == pointerToByteArrayStartingIndex[index + j])\n                        j--;\n                    if (j &lt; 0)\n                        return index;\n                    index += Math.Max(_jumpTable[pointerToByteArrayStartingIndex[index + j]] - _patternLength + 1 + j,\n                        1);\n                    Moves++;\n                }\n            }\n        }\n        return -1;\n    }\n    public unsafe (List&lt;int>, int) SearchAll(byte[] searchArray, int startIndex = 0)\n    {\n        if (_pattern == null)\n            throw new Exception(\"Pattern has not been set.\");\n        if (_patternLength > searchArray.Length)\n            throw new Exception(\"Search Pattern length exceeds search array length.\");\n        var index                 = startIndex;\n        var limit                 = searchArray.Length - _patternLength;\n        var patternLengthMinusOne = _patternLength     - 1;\n        var list                  = new List&lt;int>();\n        var Moves                 = 0;\n        fixed (byte* pointerToByteArray = searchArray)\n        {\n            var pointerToByteArrayStartingIndex = pointerToByteArray + startIndex;\n            fixed (byte* pointerToPattern = _pattern)\n            {\n                while (index &lt;= limit)\n                {\n                    var j = patternLengthMinusOne;\n                    while (j >= 0 &amp;&amp; pointerToPattern[j] == pointerToByteArrayStartingIndex[index + j])\n                        j--;\n                    if (j &lt; 0)\n                        list.Add(index);\n                    index += Math.Max(_jumpTable[pointerToByteArrayStartingIndex[index + j]] - _patternLength + 1 + j,\n                        1);\n                    Moves++;\n                }\n            }\n        }\n        return (list, Moves);\n    }\n    public int SuperSearch(byte[] searchArray, int nth, int start = 0)\n    {\n        var e = start;\n        var c = 0;\n        do\n        {\n            e = Search(searchArray, e);\n            if (e == -1)\n                return -1;\n            c++;\n            e++;\n        } while (c &lt; nth);\n        return e - 1;\n    }\n    public static bool ContainsAny(byte[] sPattern, params byte[][] list)\n    {\n        return list.Select(v => new BoyerMoore(v)).Any(bm => bm.Search(sPattern) != -1);\n    }\n    public static bool ContainsAny(string sPattern, params string[] list)\n    {\n        return list.Select(s => new BoyerMoore(s.ToLower().GetBytes(Encoding.ASCII)))\n            .Any(bm => bm.Search(sPattern.ToLower().GetBytes(Encoding.ASCII)) != -1);\n    }\n    }<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Boyer Moore Search Algorithm<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/53"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=53"}],"version-history":[{"count":1,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/53\/revisions"}],"predecessor-version":[{"id":54,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/53\/revisions\/54"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=53"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=53"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=53"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}