题目: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