KMP 字符串匹配

做 KMP 算法首先需要计算一个叫做前缀表的东西。

    

如上图所示,前缀表里面记录的是最长相等的前后缀长度

   

当 b 发生不匹配时,由于前缀表对应的数字是 1,即将数组 P 向右拖到索引为 1 的位置,如上右图。

发现还是匹配不上,继续看前缀表,这时的位置是 0,于是再拖动数组 P,如下作图所示。当不匹配的时候,

前缀表出现 -1,意味着数组 T 的当前索引需要加 1,然后拖动 P 数组使 0 位置与 T 的当前位置对齐,如下右图。

   

怎么编写代码来获得这个前缀表呢?

void PrefixTable(char pattern[], int prefix[], int n)
{
    int i = 1;
    int len = 0; 

    prefix[0] = 0;

    while (i < n) {
        if (pattern[i] == pattern[len]) {
            ++len;
            prefix[i] = len;
            ++i;
        }
        else {
            if (len > 0) {
                len = prefix[len - 1];
            }
            else {
                prefix[i] = len;
                ++i;
            }
        }
    }
}

void MovePrefixTable(int prefix[], int n)
{
    for (int i = n - 1; i > 0; --i) {
        prefix[i] = prefix[i - 1];
    }
    prefix[0] = -1;
}

void KmpSearch(char text[], char pattern[])
{
    int i = 0, j = 0;
    int n = strlen(pattern);
    int m = strlen(text);
    int* prefix = (int *)malloc(sizeof(int) * n);

    PrefixTable(pattern, prefix, n);
    MovePrefixTable(prefix, n);

    while (i < m) {
        if (j == n - 1 && text[i] == pattern[j]) {
            printf("Found pattern!\n");
            j = prefix[j];
        }
        if (text[i] == pattern[j]) {
            ++i;
            ++j;
        }
        else {
            j = prefix[j];
            if (j == -1) {
                ++i;
                ++j;
            }
        }
    }
}

 

posted @ 2020-09-21 11:04  _yanghh  阅读(176)  评论(0编辑  收藏  举报