28.Implement strStr()

Implement strStr().

Returns the index of the first occurrence of needle in haystack, or -1
if needle is not part of haystack.

实现strStr()。
找到字符串的子串位置,并返回。如果没有则返回-1

程序:

    public class ImplementStrStr
    {
        //原生字符串匹配算法
        public static int StrStrNaive(string haystack, string needle)
        {
            if (needle.Length == 0)
                return 0;
            for (int i = 0; i < haystack.Length - needle.Length + 1; i++)
            {   
                if (haystack[i] == needle[0])
                {
                    bool equal = true;
                    for (int j = 0; j < needle.Length; j++)
                    {
                        if (needle[j] != haystack[i + j])
                        {
                            equal = false;
                            break;
                        }
                    }
                    if (equal == true) return i;
                }
            }
            return -1;
        }

        //Rabin-Karp 算法
        public static int StrStrRabinKarp(string haystack, string needle)
        {
            int len = needle.Length;
            //两个特殊的用例
            if (haystack.Length < len)
            {
                return -1;
            }
            if (needle == "")
            {
                return 0;
            }

            //用于rabin-karp哈希函数的基本素数
            int basement = 256;
            //用于缩小哈希值的素数
            int prime = 31;
            //用于与要从哈希中删除的字符相乘的因子
            int factor = (int)((Math.Pow(basement, needle.Length - 1)) % prime);

            //得到指针和初始窗口的ascii值
            int needleHash = 0;
            int windowHash = 0;
            byte[] needleBytes = Encoding.ASCII.GetBytes(needle);
            byte[] windowBytes = Encoding.ASCII.GetBytes(haystack.Substring(0, len));

            //为两者生成哈希值
            for (int i = 0; i < needle.Length; i++)
            {
                needleHash = (needleHash * basement + needleBytes[i]) % prime;
                windowHash = (windowHash * basement + windowBytes[i]) % prime;
            }

            //循环找到匹配
            bool findMatch = true;
            for (int i = 0; i < haystack.Length - len + 1; i++)
            {
                //如果哈希值匹配,以防哈希值不唯一,则遍历针和窗口
                if (needleHash == windowHash)
                {
                    findMatch = true;
                    for (int j = 0; j < len; j++)
                    {
                        if (needle[j] != haystack[i + j])
                        {
                            findMatch = false;
                            break;
                        }
                    }
                    if (findMatch == true) return i;
                }
                //移动滑动窗口并找到新窗口的哈希值
                if (i < haystack.Length - len)
                {
                    byte removeByte = Encoding.ASCII.GetBytes(haystack.Substring(i, 1))[0];
                    byte addByte = Encoding.ASCII.GetBytes(haystack.Substring(i + len, 1))[0];
                    //rolling hash的函数
                    windowHash = ((windowHash - removeByte * factor) * basement + addByte) % prime;
                    //ensure the window hash to be positive
                    if (windowHash < 0)
                    {
                        windowHash += prime;
                    }

                }
            }
            return -1;
        }
    }

单元测试(通过):

 [TestClass]
    public class UnitTest28_ImplementStrStr
    {
        [TestMethod]
        public void TestMethodStrStrNaive()
        {
            string haystack = "This is an interesting problem.";
            string needle1 = "";
            string needle2 = " int";
            string needle3 = "probleem";

            Assert.AreEqual(0, ImplementStrStr.StrStrNaive(haystack, needle1));
            Assert.AreEqual(10, ImplementStrStr.StrStrNaive(haystack, needle2));
            Assert.AreEqual(-1, ImplementStrStr.StrStrNaive(haystack, needle3));
        }

        [TestMethod]
        public void TestMethodStrStrRabinKarp()
        {
            string haystack = "abc def";
            string needle = "abc";
            Assert.AreEqual(0, ImplementStrStr.StrStrRabinKarp(haystack, needle));

            haystack = "abcdef";
            needle = "cd";
            Assert.AreEqual(2, ImplementStrStr.StrStrRabinKarp(haystack, needle));

            haystack = "abcd";
            needle = "";
            Assert.AreEqual(0, ImplementStrStr.StrStrRabinKarp(haystack, needle));

            haystack = "ab";
            needle = "abc";
            Assert.AreEqual(-1, ImplementStrStr.StrStrRabinKarp(haystack, needle));

            haystack = "abcd efg";
            needle = "hij";
            Assert.AreEqual(-1, ImplementStrStr.StrStrRabinKarp(haystack, needle));

            //leetcode test case 65/72 I did not pass in the first time
            haystack = "aaaabaaabbabbaaaaaabbabbbaaabababaaaaabbbbbbbbbbbbbbbaabbbbabbaababbbababababaaaabbbbaaabababbbaaabbaabbabbbbbababbabbaabbbabaabaaaaabbbaaaaaabaaaabababababbaabaabbaaaaaaaababbabaa";
            needle = "aabbaaaabbbbaabaaabaabbaaababbabbbbbaba";
            //Assert.AreEqual(-1, ImplementStrStr.StrStrRabinKarp(haystack, needle));

            haystack = "baabbaaaaaaabbaaaaabbabbababaabbabbbbbabbabbbbbbabababaabbbbbaaabbbbabaababababbbaabbbbaaabbaababbbaabaabbabbaaaabababaaabbabbababbabbaaabbbbabbbbabbabbaabbbaa";
            needle = "bbaaaababa";
            Assert.AreEqual(107, ImplementStrStr.StrStrRabinKarp(haystack, needle));
        }


    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值