{"id":527,"date":"2022-03-06T16:59:13","date_gmt":"2022-03-06T16:59:13","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=527"},"modified":"2022-03-06T16:59:13","modified_gmt":"2022-03-06T16:59:13","slug":"boyermoorestring-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2022\/03\/06\/boyermoorestring-cs\/","title":{"rendered":"BoyerMooreString.cs"},"content":{"rendered":"\n<p>BoyerMoore String Searching 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;\npublic class BoyerMooreString\n{\n    private       int[]  _jumpTable;\n    private       string _pattern;\n    private       int    _patternLength;\n    public BoyerMooreString()\n    {\n    }\n    public BoyerMooreString(string pattern)\n    {\n        SetPattern(pattern);\n    }\n    public void SetPattern(string pattern)\n    {\n        _pattern       = pattern;\n        _jumpTable     = new int[ushort.MaxValue];\n        _patternLength = _pattern.Length;\n        for (var index = 0; index &lt; ushort.MaxValue; ++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(string searray, int startIndex = 0)\n    {\n        if (_pattern == null)\n            throw new Exception(\"Pattern has not been set.\");\n        if (_patternLength > searray.Length)\n            throw new Exception(\"Search Pattern length exceeds search array length.\");\n        var num1 = startIndex;\n        var num2 = searray.Length - _patternLength;\n        var num3 = _patternLength - 1;\n        var num4 = 0;\n        fixed (char* chPtr1 = searray)\n        {\n            var chPtr2 = chPtr1 + startIndex;\n            fixed (char* chPtr3 = _pattern)\n            {\n                while (num1 &lt;= num2)\n                {\n                    var index = num3;\n                    while (index >= 0 &amp;&amp; chPtr3[index] == chPtr2[num1 + index])\n                        --index;\n                    if (index &lt; 0)\n                        return num1;\n                    num1 += _jumpTable[chPtr2[num1 + index]];\n                    ++num4;\n                }\n            }\n        }\n        return -1;\n    }\n    public unsafe (List&lt;int>, int) SearchAll(string searray, int startIndex = 0)\n    {\n        if (_pattern == null)\n            throw new Exception(\"Pattern has not been set.\");\n        if (_patternLength > searray.Length)\n            throw new Exception(\"Search Pattern length exceeds search array length.\");\n        var num1    = startIndex;\n        var num2    = searray.Length - _patternLength;\n        var num3    = _patternLength - 1;\n        var intList = new List&lt;int>();\n        var num4    = 0;\n        fixed (char* chPtr1 = searray)\n        {\n            var chPtr2 = chPtr1 + startIndex;\n            fixed (char* chPtr3 = _pattern)\n            {\n                while (num1 &lt;= num2)\n                {\n                    var index = num3;\n                    while (index >= 0 &amp;&amp; chPtr3[index] == chPtr2[num1 + index])\n                        --index;\n                    if (index &lt; 0)\n                        intList.Add(num1);\n                    num1 += _jumpTable[chPtr2[num1 + index]];\n                    ++num4;\n                }\n            }\n        }\n        return (intList, num4);\n    }\n    public int SuperSearch(string searray, int nth, int start = 0)\n    {\n        var startIndex = start;\n        var num1       = 0;\n        do\n        {\n            var num2 = Search(searray, startIndex);\n            if (num2 == -1)\n                return -1;\n            ++num1;\n            startIndex = num2 + 1;\n        } while (num1 &lt; nth);\n        return startIndex - 1;\n    }\n    public class BMPartialPatternSearchString\n    {\n        public int MinimumSearchLength;\n        public BMPartialPatternSearchString(int min = 5)\n        {\n            MinimumSearchLength = min;\n        }\n        public (string partialPattern, int idx) SearchPartial(string pattern, string searray)\n        {\n            BoyerMooreString boyerMooreString = new BoyerMooreString(pattern);\n            var              length           = pattern.Length;\n            var              stringList       = new List&lt;string>();\n            if (length &lt; MinimumSearchLength)\n                throw new Exception(\"Search Pattern less than minimum search length.\");\n            var startIndex          = 0;\n            var minimumSearchLength = MinimumSearchLength;\n            do\n            {\n                var pattern1 = pattern.Substring(startIndex, minimumSearchLength);\n                stringList.Add(pattern1);\n                boyerMooreString.SetPattern(pattern1);\n                int num = boyerMooreString.Search(searray);\n                if (num != -1)\n                    return (pattern1, num);\n                if (startIndex + minimumSearchLength >= length)\n                {\n                    startIndex = 0;\n                    ++minimumSearchLength;\n                }\n                else\n                {\n                    ++startIndex;\n                }\n            } while (minimumSearchLength != length + 1);\n            return (pattern, -1);\n        }\n        public List&lt;(string partialPattern, int idx)> SearchPartialFirst(\n            string pattern,\n            string searray)\n        {\n            BoyerMooreString boyerMooreString = new BoyerMooreString(pattern);\n            var              length           = pattern.Length;\n            var              valueTupleList   = new List&lt;(string, int)>();\n            var              stringList       = new List&lt;string>();\n            if (length &lt; MinimumSearchLength)\n                throw new Exception(\"Search Pattern less than minimum search length.\");\n            var startIndex          = 0;\n            var minimumSearchLength = MinimumSearchLength;\n            do\n            {\n                var pattern1 = pattern.Substring(startIndex, minimumSearchLength);\n                stringList.Add(pattern1);\n                boyerMooreString.SetPattern(pattern1);\n                int num = boyerMooreString.Search(searray);\n                if (num != -1)\n                    valueTupleList.Add((pattern1, num));\n                if (startIndex + minimumSearchLength >= length)\n                {\n                    startIndex = 0;\n                    ++minimumSearchLength;\n                }\n                else\n                {\n                    ++startIndex;\n                }\n            } while (minimumSearchLength != length + 1);\n            return new List&lt;(string, int)>\n                { (pattern, -1) };\n        }\n        public List&lt;(string partialPattern, int idx)> SearchPartialAll(\n            string pattern,\n            string searray)\n        {\n            BoyerMooreString boyerMooreString = new BoyerMooreString(pattern);\n            var              length           = pattern.Length;\n            var              valueTupleList   = new List&lt;(string, int)>();\n            var              stringList       = new List&lt;string>();\n            if (length &lt; MinimumSearchLength)\n                throw new Exception(\"Search Pattern less than minimum search length.\");\n            var startIndex          = 0;\n            var minimumSearchLength = MinimumSearchLength;\n            do\n            {\n                var pattern1 = pattern.Substring(startIndex, minimumSearchLength);\n                stringList.Add(pattern1);\n                boyerMooreString.SetPattern(pattern1);\n                (List&lt;int>, int) tuple = boyerMooreString.SearchAll(searray);\n                if (tuple.Item1.Count > 0)\n                    foreach (var num in tuple.Item1)\n                        valueTupleList.Add((pattern1, num));\n                if (startIndex + minimumSearchLength >= length)\n                {\n                    startIndex = 0;\n                    ++minimumSearchLength;\n                }\n                else\n                {\n                    ++startIndex;\n                }\n            } while (minimumSearchLength != length + 1);\n            return valueTupleList;\n        }\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>BoyerMoore String Searching Algorithm<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[161,228,101,27],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/527"}],"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=527"}],"version-history":[{"count":1,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/527\/revisions"}],"predecessor-version":[{"id":528,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/527\/revisions\/528"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=527"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=527"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=527"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}