[LeetCode] Implement strStr()[字符串hash]

题目: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,给两个串A和B,总B是不是A的子串,如果是,返回第一个子串的起始位置,不是返回-1
  • 解法:看完知道最简单的是n方暴力枚举起点判断,这题数据比较水,能过,不过如果串的长度长一些,数据加强一些就不行了,当然不是我们想要的解法,比较科学的算法是KMP,网上基本上都是KMP的解法,所以我用了另外一种人品算法:字符串hash.
  • 过程:字符串hash说了也很简单,网上对于hash的讲解无限多,我就不管了,这里就把A串中起点到每一个位置的hash值保存起来,然后把其中的某个hash值减去前面一段剩下的(长度为B串的长度)就是A串中的一个子串了,然后再看这个子串的hash值和B串是否相等.
  • 假设A=”1234567”,B=”345”,我们定hash算法的魔法(进制)值为10,那么A的一个前缀串为”12345”,减去前缀”12”剩下”345”,这时候hash值和B串的hash值相等,返回返回位置2.这里减法就是hash值进行相减就可以了,具体hash运(教)算(程)请自行搜索或者看下面代码.
  • 时间复杂度:O(n),空间复杂度O(n),所以可以满足串比较长的情况.

C++代码:

class Solution {

public:
    typedef unsigned long long ULLONG;
    std::vector<ULLONG>m_aulHashValues;
    int strStr(string haystack, string needle) {
        int iLength = needle.size();
        int magic = 131;//魔法(进制)值.
        ULLONG ulHayHash = 0; //haystack串的过程hash值.
        ULLONG ulPower = 1; //magic的iLength次方.
        ULLONG ulNeedleHash = 0; //needle串的总hash值
        for (int i = 0; i < iLength; ++i) {
            ulPower *= magic;
            ulNeedleHash = ulNeedleHash * magic + needle[i]; //needle的hash值.
        }
        for (int i = 0; i < iLength; ++i) {
            ulHayHash = ulHayHash * magic + haystack[i];
            m_aulHashValues.push_back(ulHayHash);
        }
        if (ulHayHash == ulNeedleHash) return 0;
        int iResult = -1;
        for (int i = iLength; i < (int)haystack.size(); ++i) {
            ulHayHash = ulHayHash * magic + haystack[i];
            if (ulHayHash - m_aulHashValues[i - iLength]*ulPower == ulNeedleHash) {
                iResult = i - iLength + 1;
                break;
            }
            m_aulHashValues.push_back(ulHayHash);
        }

        return iResult;
    }
};

欢迎访问我的github,我的leetcode持续更新: https://github.com/tsfissure/LeetCode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值