void getNext(char* p,int next[])
{
int len = strlen(p);
int i = 0, j = -1;
next[i] = j;
while (i < len - 1) {
//p[j]表示前缀,p[i]表示后缀
if (j == -1 || p[i] == p[j]) {
i++, j++;
next[i] = j;
}
else
j = next[j];
}
}
next[i]保存的是,对于第i个字符来说,在字符串str[0] -- str[i-1]中,字符串前next[i]个字符与后next[i]个字符相匹配,即前缀与后缀匹配的长度为next[i]
e.g aaabcdaaac,比如这里的第10个字符c,前缀与后缀匹配长度为3,则next[9] = 3.
kmp加快的过程就在于此,当比较到字符c时,发现c不匹配,那么可以直接从next[9] = 3下标即'b'开始继续匹配。因为比较到c才发现不匹配,说明c之前的都匹配成功了,说明原串前面一部分是跟c的前面一部分相同的,如果整个串想要匹配成功那么c前面原串那部分字符必须保证还是匹配的。所以直接移到下标3,因为只有3前面的字符串与c前面的字符串(即与原串相同部分)匹配。
优化版getNext:
void getNext(char* p,int next[])
{
int len = strlen(p);
int i = 0, j = -1;
next[i] = j;
while (i < len - 1) {
//p[j]表示前缀,p[i]表示后缀
if (j == -1 || p[i] == p[j]) {
i++, j++;
if(p[i] != p[j])
next[i] = j;
else //如果p[i]==p[j],则继续往前推。因为在这种情况下,p[i]匹配失败,p[j]必然匹配失败。所以可以优化
next[i] = next[j];
}
else
j = next[j];
}
}
kmp匹配过程:
int kmp(char* s, char* p)
{
int i = 0;
int j = 0;
int sLen = strlen(s), 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;
}