方法一 j | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
---|---|---|---|---|---|---|---|---|---|---|---|
P[j] | a | b | a | b | a | b | a | b | c | a | |
f(j) | -1 | -1 | 0 | 1 | 2 | 3 | 4 | 5 | -1 | 0 | |
next[j] | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | 1 |
f(j)代表一个以数i为结尾的后缀和以下标为f(i)为结尾的前缀相同。
next[j]
函数表示对于模式串失配位置j+1
,下一轮匹配时模式串的起始位置(即对齐于主串的失配位置);则
next[j]=f(j)+1,即通过前一个数的next【i】找到新的起始位置(即对齐于主串的失配位置)
代码实现
部分匹配函数(失配函数)的C实现代码:
int *fail(char *p) {
int len = strlen(p);
int *f = (int *) malloc(len * sizeof(int));
f[0] = -1;
int i, j;
for(j = 1; j < len; j++) {
for(i = f[j-1]; ; i = f[i]) {
if(p[j] == p[i+1]) {
f[j] = i + 1;
break;
}
else if(i == -1) {
f[j] = -1;
break;
}
}
}
return f;
}
KMP的C实现代码:
int kmp(char *t, char *p) {
int *f = fail(p);
int i, j;
for(i = 0, j = 0; i < strlen(t) && j < strlen(p); ) {
if(t[i] == p[j]) {
i++;
j++;
}
else if(j == 0)
i++;
else
j = f[j-1] + 1;
}
return j == strlen(p) ? i - strlen(p) : -1;
}
方法二
void getnext(int len){
int i=0,j=-1;
next[0]=-1;
while(i<len){
if(j==-1 || str[i]==str[j]){
i++;j++;
next[i]=j;
}else
j=next[j];
}
}
-1 0 0 1 2 3 4 5 6 -1
0 1 2 3 4 5 6 7 8 9
a b a b a b a b c b
原理:next数组标记着这个位置不再匹配时要去哪个位置从新开始,也就是说若next[i]>0,则失配位置的前一个位置是匹配的。