字符串:KMP算法,实现strStr()
代码:
class Solution {
public:
int strStr(string haystack, string needle) {
if(needle.size() == 0)
return 0;
vector<int> next(needle.size(), 0);
getNext(next, needle);
int j = 0;
for(int i = 0; i < haystack.size(); i++)
{
while(j > 0 && haystack[i] != needle[j])
{
j = next[j - 1];
}
if(haystack[i] == needle[j])
{
j++;
}
if(j == needle.size())
{
return i - needle.size() + 1;
}
}
return -1;
}
void getNext(vector<int> &next, const string& s)
{
//next【i】数组:表示【0,i】的最长相等前后缀长度
//aabaaf的next数组为:010120,next【5】表示aabaa的最长前后缀长度为2,next【6】表示aabaaf的最长前后缀长度为0.
//i:指向后缀的最后一个字符,后缀:从(0,n】开始到n的子串
//aabaaf的前缀(不包含最后一个字符)
//1.a
//2.aa
//3.aab
//4.aaba
//5.aabaa
//j:指向前缀的最后一个字符,前缀:从0开始到【0,n)的子串
//aabaaf的后缀(不包含第一个字符)
//1.f
//2.af
//3.aaf
//4.baaf
//5.abaaf
//思想:动态规划,计算局部最长前后缀,再到整体
//初始化
int j = 0;
next[0] = 0;
for(int i = 1; i < s.size(); i++)
{
/*错误
aabaaac
回退了后要加回来,先while的顺序一定不能变!!
if(s[i] == s[j])
{
j++;
next[i] = j;
}
else
{
while(j > 0 && s[i] != s[j])
{
j = next[j - 1];
next[i] = j;
}
}
*/
//重点:while而非if,需要多次回退直到相等
while(j > 0 && s[i] != s[j])
{
//回退到上一次的比较情况,不理解的话可以参考下之前写过的动态规划的一道题目,求最长公共子串。
j = next[j - 1];
}
if(s[i] == s[j])
{
j++;
}
next[i] = j;
}
}
};