1. 程式人生 > >KMP演算法程式碼註釋

KMP演算法程式碼註釋

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void printNext(int next[], int size) {
    for(int i = 0; i < size;++i)
        printf("%d  ", next[i]);
    printf("\n\n");
}

// next[i]表示[0,...,i-1]的子串的最長公共前後綴長度
void getNext(char *p, int next[]) {
    int len = strlen(p);
    next
[0] = -1; //初值為-1 int k = -1; // 表示[0,...,j]的nextint j = 0; while(j < len - 1) { if(k == -1 || p[j] == p[k]) { // 匹配或者是沒有公共前後綴 ++j; ++k; next[j] = k; } else k = next[k]; //由於出現不匹配現象,需要找更短的字首 } } int kmp(char *s, char *p
) { int pLen = strlen(p), sLen = strlen(s); int *next = malloc(sizeof(int) * pLen); getNext(p, next); printNext(next, pLen); int i = 0, j = 0; while(i < sLen && j < pLen) { if(j == -1 || s[i] == p[j]) { ++i; ++j; } else
// 當出現不匹配時,只需要將模式串向後移動[匹配長度 - next[j]] j = next[j]; } free(next); if(j == pLen) return i - j; return -1; } int main() { char *s = "BBC ABCDAB ABCDABCDABDE", *p = "ABCDABD"; int pos = kmp(s, p); printf("%d\n", pos); if(pos != -1) { printf("%s\n", s); printf("%*s\n", pos + strlen(p), p); } return 0; }

總結

1. next陣列是其前面的子串的最長公共前後綴長度
2. 在求next陣列的時候,要利用前面匹配的資訊。如果p[j] == p[k],
那麼next[j] = k + 1;反之,需要在其字首中找到一個字母等於p[j],
如果沒有的話,那麼next[j] = 0,有的話,next[j]=k+1,這裡的k不再是
next[j-1]。