Leetcode刷题笔记 KMP算法
KMP算法代码
Leetcode T28:
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
自用超详细注释版c++代码
class Solution {
public:
/*创建一个存储部分匹配值PM的next数组,即next[i]是t[0:i]的最长公共前后缀的长度。
next数组的意义:
当主串的某个字符x与模式串的t[i+1]失配时,x应与模式串的子串t[0:i]的最长公共前缀的下一个字符进行比较
由于字符的下标从0开始,所以最长公共前缀的下一个字符的下标就等于t[0:i]的最长公共前缀的长度。
总结:
当主串字符与模式串的t[i]失配时,应改为与模式串的t[next[i-1]]进行比较。
*/
void creatNext(string t, vector<int> &next){
//在创建next数组时,可将待求next值的字符,即i指向的字符,视为主串的字符x,将t[0:next[i-1]](即t[0:j],因为next[i++]=++j)视为模式串。
//定义指针
int j=0;//j指向前缀末尾,其值等价于最长公共前后缀的长度
int i=1;//i指向后缀末尾,即next数组待填入数字的位置
//初始化next数组
next[0]=0;
//更新next数组
while(i<t.size()){
//i指向的字符与next[i-1]指向的字符匹配,所以,填写next[i]的值,i和j均自增
if(t[i]==t[j]){
next[i++]=++j;
}
else{
//i指向的字符与next[i-1]指向的字符不匹配,所以,根据next表往前遍历寻找能与i指向的字符匹配的位置
while(j!=0&&t[i]!=t[j]){
j=next[j-1];
}
if(t[i]==t[j]){
//找到与i指向的字符匹配的字符
next[i++]=++j;
}
else{
//没有公共前后缀,next[i]值为0,i自增j不动
next[i++]=0;
}
}
}
}
int strStr(string haystack, string needle) {
vector<int> next(needle.size());
creatNext(needle,next);
int j=0;//指向模式串
int i=0;//指向主串
for(i=0;i<haystack.size()&&j<needle.size();i++){
while(j!=0&&haystack[i]!=needle[j]){
j=next[j-1];
}
if(haystack[i]==needle[j]){//字符匹配则i和j同时增大,否则只有i增大
j++;
}
}
if(j==needle.size())return i-needle.size();//j走完了needle,说明匹配完成
return -1;
}
};