利用前缀表 (最长相等(公共)前后缀)进行 模式串与字符串的匹配
前缀:包含首字母,不包含尾字母的所有子串
后缀:包含尾字母,不包含首字母的所有子串
第一个字母不存在前缀和后缀
next(前缀表)数组构造
//传入匹配字符
next function(s){
//初始化数组
let next=[];
next[0]=0; //第一个匹配字符没有最长相等前缀,所以前缀表[0]=0;
//j前缀末尾,i后缀末尾
//结合前面定义,j=除了尾字母的最后一个字母,i=最后一个 尾字母
let j=0;
for(let i=1;i<s.length;i++){ //有了第一个匹配字符有前缀表,我们从第二个匹配字符开始
//前后缀不相等
while(j>0&&s[i]!==s[j]){//j=0是没有最长相等前后缀,j>0是因为next[j-1]会越界
//j=前一位对应的下标
j=next[j-1];
}
//前后缀相等
if(s[i]===s[j]){
j++;
}
next[i]=j;
}
return next;
}
kmp主函数:
KMP function(s,p){//s=匹配字符,p=模式字符
//获取next数组
let next=next(p);
//i匹配串指针指针,j模式字符串指针
let i=0,j=0;
while(i<s.length&&j<p.length){
if(s[i]===p[j]){
i+=1;j+=1;
}else if(j>0){
j=next[j-1];
}else{
i++;
}
}
return i-j;
}