【问题标题】:KMP string matching algorithm:Auxillary array outputKMP字符串匹配算法:辅助数组输出
【发布时间】:2012-03-26 09:26:58
【问题描述】:

这是我的KMP字符串匹配算法的实现。 当我检查 pi 数组时,它存储 0、1、2、3、4、5、6。但根据算法书籍,它应该是 0,0,1,2,3,0,1。我的代码也给出了正确的结果。我不明白为什么会这样,还是我做错了什么?如果是这样,请纠正我。

谢谢。

#include<iostream>
#include<string>
#include<string.h>

using namespace std;

int* ComputePrefix(char P[])
{
    size_t m = strlen(P);
    int *pi = new int[m];
    pi[0] = 0;
    int k = 0;

    for(int q =0; q < m; q++)
    {
        if( k > 0 && P[k+1] != P[q])
            k = pi[k];

        if( P[k+1] == P[q])
            {
                pi[q] = k;
                k = k + 1;
            }
            pi[q]=k;
    }

    return (pi);
}

void KMP_Matcher(char T[], char P[])
{

    size_t n = strlen(T);
    size_t m = strlen(P);

    int *pi = new int[m];
    pi = ComputePrefix(P);

    cout<<endl;


    int q =0;
    for (int i = 0; i <= n; i++)
    {
        if( q > 0 && P[q] != T[i] )
        {
            q = pi[q - 1];
        }


        else if( P[q] == T[i])
        {


            if( q == m-1)
            {
                cout<<"Shift occurs at : "<< i-q <<endl;
                q = pi[q];
            }
            else q = q + 1;
        }

        else q++;
    }
}


int main()
{
    char T[] = "abababacaba";
    char P[] = "ababaca";

    KMP_Matcher(T,P);
    return 0;
}

【问题讨论】:

    标签: c++ algorithm string-matching


    【解决方案1】:

    您的跳转表构造函数根本不检查针头的前缀。我们希望能够针对针中的每个位置查找通向(但不包括)该位置的针的最长可能正确前缀的长度,而不是完整前缀从刚刚匹配失败的needle[0] 开始;这是我们在寻找下一场比赛时必须回溯的距离。因此,跳转表中的每个条目(例如,table[i])正是针的最长可能正确前缀的长度,它也是以needle[i - 1] 结尾的子字符串的前缀。

    跳转表中的前两个条目是 -1 和 0,因为 a) 模式开头的不匹配不会触发回溯(或者,换句话说,零长度的前缀不能有任何正确的前缀或suffixes) 和 b) 空字符串的长度被认为是 0。

    更多详情请查看wikipedia或算法教科书。

    完成上面的代码是:

    int *build_jump_table(const char * target)
    {
        if(!target)
            return NULL;
        int *table = new int[strlen(target) + 1];
        if(!table)
            return NULL;
        table[0] = -1; /* unused by the matcher, just used here */
    
        for(int i = 0; target[i] != '\0'; i++) {
            table[i+1] = table[i] + 1;
            while(table[i+1] > 0 && target[i] != target[table[i+1] - 1]) {
                table[i + 1] = table[table[i + 1] - 1] + 1;
            }
        }
        return table;
    }
    

    相当冗长,当你理解了跳转表背后的概念后,可以简化很多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-02
      • 2017-02-10
      • 2016-10-16
      • 1970-01-01
      • 2021-07-21
      • 1970-01-01
      • 2019-03-05
      • 2013-12-24
      相关资源
      最近更新 更多