题目
题解
KMP算法
先求next数组,next数组的含义为:
当前位置前面的元素的最长相等前缀和后缀的长度,例如字符串“aabcaabd”的元素d,也就是第8个元素str[7],前面的元素“aabcaabd”最长相等前缀和后缀为“aab”,其对应的next数组的值next[7] = 3。
class Solution {
public:
int strStr(string haystack, string needle) {
if(haystack.size() < needle.size()) return -1;
vector<int> next(needle.size(), 0);
next[0] = -1;
if(next.size() != 1)
{
next[1] = 0;
int cn = 0;
int i = 2;
while(i < needle.size() )
{
if(needle[cn] == needle[i - 1])
{
next[i++] = ++cn;
}
else if(cn > 0)
{
cn = next[cn];
}
else
{
next[i++] = 0;
}
}
}
int p1 = 0;
int p2 = 0;
while(p1 < haystack.size() && p2 < needle.size() )
{
if(haystack[p1] == needle[p2])
{
p1++;
p2++;
}
else if(p2 == 0)
{
p1++;
}
else
{
p2 = next[p2];
}
}
if(p2 == needle.size()) return p1 - p2;
return -1;
}
};
举一反三
leetcode旋转字符串
可以看成KMP问题,将两个s字符串首尾拼接起来,原题就是判断goal是否为s子串的KMP问题
class Solution {
public:
bool rotateString(string s, string goal) {
if(s.size() != goal.size()) return false;
s = s + s;
return KMP(s, goal);
}
bool KMP(string s, string goal)
{
//求next数组
vector<int> next(goal.size(), 0);
next[0] = -1;
if(next.size() != 1)
{
next[1] = 0;
int i = 2;
int cn = 0;
while(i < next.size())
{
if(goal[cn] == goal[i - 1])
{
next[i++] = ++cn;
}
else if(cn > 0)
{
cn = next[cn];
}
else
{
next[i++] = 0;
}
}
}
//KMP
int p1 = 0;
int p2 = 0;
while(p1 < s.size() && p2 < goal.size())
{
if(s[p1] == goal[p2])
{
p1++;
p2++;
}
else if(p2 > 0)
{
p2 = next[p2];
}
else{
p1++;
}
}
return p2 == goal.size() ;
}
};