Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ KMP字符串匹配算法:辅助数组输出_C++_Algorithm_String Matching - Fatal编程技术网

C++ KMP字符串匹配算法:辅助数组输出

C++ KMP字符串匹配算法:辅助数组输出,c++,algorithm,string-matching,C++,Algorithm,String Matching,这是我对KMP字符串匹配算法的实现。 当我检查pi数组时,它存储0,1,2,3,4,5,6。但是根据algo书籍,它应该是0,0,1,2,3,0,1。我的代码也给出了正确的结果。我不明白为什么会发生这种情况,或者我做错了什么?如果是这样,请纠正我 谢谢 #include<iostream> #include<string> #include<string.h> using namespace std; int* ComputePrefix(char P[]

这是我对KMP字符串匹配算法的实现。 当我检查pi数组时,它存储0,1,2,3,4,5,6。但是根据algo书籍,它应该是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;
}
#包括
#包括
#包括
使用名称空间std;
int*ComputePrefix(字符P[]
{
尺寸m=strlen(P);
int*pi=新的int[m];
pi[0]=0;
int k=0;
对于(int q=0;q0&&P[k+1]!=P[q])
k=pi[k];
if(P[k+1]==P[q])
{
pi[q]=k;
k=k+1;
}
pi[q]=k;
}
回报率(pi);
}
无效KMP_匹配器(字符T[],字符P[]
{
尺寸n=strlen(t);
尺寸m=strlen(P);
int*pi=新的int[m];
pi=计算公式(P);

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

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

有关更多详细信息,请参阅或阅读算法教科书

实现上述功能的代码是:

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;
}

这是非常详细的,当您理解跳转表背后的概念时,可以简化很多。

您的跳转表构造函数根本不检查指针的前缀。我们希望能够查找指针中每个位置的最长正确前缀长度,直到(但不包括)该位置,除了从
指针[0]
开始的完整前缀没有匹配;这是我们在查找下一个匹配时必须回溯的距离。因此跳转表中的每个条目(例如,
表[i]
)正是指针可能的最长正确前缀的长度,该前缀也是以
指针[i-1]
结尾的子字符串的前缀

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

有关更多详细信息,请参阅或阅读算法教科书

实现上述功能的代码是:

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;
}
这非常冗长,当您理解跳转表背后的概念时,可以简化很多