KMP算法

筅森魡賤 提交于 2019-11-29 10:16:28

朴素的字符串匹配算法

这是最容易理解的字符串匹配算法,我们用两个指针ai,bi分别指待匹配串a模式串b的起始位置,当a[ai]==b[bi]时ai++,bi++,一旦失配,ai=ai-bi+1(原来位置的后一位),bi=0;
显然这种方法不断重复访问模式串的前部分使得匹配速度变慢
例如
a串:aaaaaaaaaaaaaaaaab
b串:aaaaaaaaaab
每次匹配时我都要将b串访问一遍,原因在于每次匹配失败我都将bi回到0;
对于这里的改进就要引入next数组来记录一个合适的位置使得bi不用每次都回到0

next数组

    int next[b.size()];
    for(int i=1;i<b.size();i++) next[i]=0;
    next[0]=-1;
    next[1]=0;
    for(int i=2;i<b.size();i++)
    {
        int k=next[i-1];
        if(b[k]==b[i-1]) next[i]=k+1;
        else
        {
            while(k!=-1)
            {
                k=next[k];
                if(b[k]==b[i-1]) break;
            }
            next[i]=k+1;
        }
    }

这里是kmp算法最重要的部分

  1. next数组的作用是当第i位的字符失配的时候bi回到next[bi]的位置
  2. next[i]的实际意义是 i位置以前的next[i]个字符(不包括 i ) 和从0开始的前 i 个字符(也即是 next[i]位置以前的next[i]个字符(不包括next[i]))相等。因此我们可以得出b [ i ]==b [ next [ i ] ] 时next [ i+1 ] = next [ i ]+1
  3. 同上i,next[i]和next[next[i]]的前next[next[i]]个字符相等,当不满足2时,如果b[next[next[i]]==b[i],那么next[i+1]=next[next[i]]+1,同理我可以一直递归下去知道next的值等于0;

匹配

    for(int i=0,j=0;i<a.size();)
    {
        if(a[i] == b[j])
        {
            i++;
            j++;
        }
        else
        {
            if(j==-1)
            {
                i++;
                j++;
            }
            else j=next[j];
        }
        if(j==b.size()) return true;
    }
    return false;

当a[ai] == b[bi] 时正常匹配,当失配时让bi回到next[bi],继续匹配a[ai]和b[bi],直到next[bi] == -1,表示已经找完了,都没发现可以匹配的,所以ai++,bi++;

小结

我们可以看出next数组和匹配的代码部分很相似,实际上,求next数组时模式串自我匹配的过程。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!