本文用于自己观看回忆KMP算法
KMP算法简介
1.可在一个主文本字符串S内查找一个词W的出现位置。
2.其流程大致分为两步,第一为构造next数组。第二部分利用next数组来实现模式串w与S的匹配,找到字符串S中w第一次出现的位置(索引)。
Next数组
-
首先Next数组元素定义为,该字符之前的字符串中具有相同前缀后缀的长度为多少。例: 给定S串“DABCDABDE”,设他的next数组 P,P数组所存的值应该依次为[-1,0,0,0,0,1,2,3,1]。
其中,E对应的next 值为1(即字符E之前的字符串“DABCDABD”中有长度为1的相同前缀和后缀)。
-
Next数组代码
void GetNext(char* p,int next[])
{
int pLen = strlen(p);
next[0] = -1;
int k = -1;
int j = 0;
while (j < pLen - 1)
{
//p[k]表示前缀,p[j]表示后缀
if (k == -1 || p[j] == p[k])
{
++k;
++j;
next[j] = k;
}
else
{
k = next[k];
}
}
}
因为next数组元素含义的定义,所以当P[i] == P[k]时,先使得k++,i++(k在这里可以表示为匹配的最长前缀后缀长度),再使得next[j] = k;
当P[j] != P[k]时,让P[next[k]]再与P[j]尝试匹配(当next[k]!=0时,P[next[k]-1] ==p[j-1]),直到匹配P[j]成功,或者是k=-1,匹配失败。放弃继续匹配P[j],通过j++,k++。开始匹配p[j+1],同时next[j+1]设为0,表示0-j的字串最长相同前缀后缀长度为0;
例题:Leetcode 1392最长快乐前缀.
模式串匹配
模式串匹配时,匹配成功一个字符和匹配失败一个字符时,和构造next数组时处理方法相似。代码也都相似。
int KmpSearch(char* s, char* p)
{
int i = 0;
int j = 0;
int sLen = strlen(s);
int pLen = strlen(p);
while (i < sLen && j < pLen)
{
//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if (j == -1 || s[i] == p[j])
{
i++;
j++;
}
else
{
//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
//next[j]即为j所对应的next值
j = next[j];
}
}
if (j == pLen)
return i - j;
else
return -1;
}
Leetcode 214最短回文串.