Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
题意
两个字符串
haystack和needle ,如果needle是haystack的子串,返回needle在haystack中出现的索引,如果needle不是haystack的子串,返回-1;
题解
可以暴力破解,就是逐一比较。这样的时间复杂度是O(M*N)
最好的方法是kmp算法,我这里推荐一篇非常简单明了的文章,我也是看这篇文章搞懂了kmp
难点就是建立公共前后缀数组(next数组),
原理就是这样,但是代码实现过程也比较难理解,这里也简单介绍一下代码实现过程:
getNext中,next[i]为前i个字符里公共前后缀的个数减1
(表示字符索引)。i从0到
needle.length() - 1遍历,j为此时公共前后缀的个数减1(表示字符索引),
先说needle[i]==needle[j]的情况,此时索引0-j的字符与i-j到i-1的字符是相等的,判断第i个和第j+1个是否相等,相等则j+1
其次是needle[i]!=needle[j]的情况,这个情况比较难理解
图中黄色部分是相等的,因此
图中红色部分也是相等的。这样0-next[j]与i-next[j]到i也是相等的,这样循环找到最大公共前后缀,直到needle[j]==needle[i]或者next[j]=-1。
这样,就可以做出needle的next数组了。
最后就是needle和haystack匹配,匹配方法相同。
class Solution {
public:
int strStr(string haystack, string needle) {
if (haystack.empty()) return needle.empty() ? 0 : -1;
if (needle.empty()) return 0;
vector<int> next(needle.length() + 1);
getNext(next, needle);
int i = 0, j =-1;
for (i=0;i< haystack.length();i++)
{
while (j != -1 && haystack[i] != needle[j+1])
j = next[j];
if(haystack[i]==needle[j+1])
j++;
if(j==needle.length()-1)
return i-j;
}
return -1;
}
void getNext(vector<int> &next, string &needle) {
int i = 0, j = -1;
next[i] = j;
for(i=1;i!=needle.length();i++)
{
while (j != -1 && needle[i] != needle[j+1])
j = next[j];
if (needle[i] == needle[j+1]) j++;
next[i] = j;
}
}
};