字符串模式匹配(简单模式匹配算法与KMP算法)(一)

一般的字符串模式匹配算法是类似下面的逐次匹配,举例说明如下

主串s=ababcabcacbab

从串t=abcac

一般匹配方法如下图所示

《字符串模式匹配(简单模式匹配算法与KMP算法)(一)》

代码如下

int index(string s,string t)
{
    int i=0,j=0;
    int l1=s.length();
    int l2=t.length();
    while(i<=l1-1&&j<=l2-1)
    {
        if(s[i]==t[j])
        {
            ++i;
            ++j;
        }
        else
        {
            if(j==0)
            {
                ++i;
            }
            else
            {
                i=i-j+2;
                j=0;
            }

        }
        //cout<<“i=”<<i<<“j=”<<j<<endl;
    }
    if(j>l2-1) return i-l2;
    else return 0;
}

这样算下来的时间复杂度是O(l1*l2),因为每次只要中间发生字符串s[i]和t[j]不相等,这种算法会把字符串t的索引置为0,而主串s也是从之前开始匹配的i加一个1,其实我们可以发现,中间有些比较是不必要的,比如从第三趟比较就可以看出主串中第4,5,8个字符串是‘b’,’c’,’a’,(对应模式串中的第2,3,4个字符)。而模式串t中第一个字符是a,所以其实不需要和这几个字符相比较了,只需要将模式向右滑动3个字符即可。这样的匹配过程中,实际上主串i没有回溯,只是模式串的j在变化,就降低了时间复杂度为O(l1+l2),这也就是kmp算法。

kmp算法每趟比较过程让模式串向后滑动一个合适的位置,这个合适的位置我们可以算出来,一般称这个位置叫next表。

先写出next表的定义,接下来再解释为什么这样定义

《字符串模式匹配(简单模式匹配算法与KMP算法)(一)》

 

结合这个图来解释

《字符串模式匹配(简单模式匹配算法与KMP算法)(一)》

先说一下,上面两个图中的S0和T0分别代表的是两个穿的长度,真正的字符串都从下标1开始。

1)当j=1时,也就是说模式串的第一个字符就与当前位置s对应的字符不同,此时主串的下标应该+1,再和模式串第一个字符进行比较;

2)当两个串匹配到此处时,前j-1个字符都是匹配的,到了第j个字符就不同了,此时需要把字符串t向右移动max{k}个位置。

这个k应该满足1<k<j并且p1…pk-1=pj-k+1…pj-1.k的值可能有多个,为了不使向右移动丢失可能的匹配,选择最大的一个k,也就是max{k},其最大值为j-1;

3)除了上面两种情况,发生匹配时,主串指针i不回溯,在最坏情况下,模式串从第1个字符开始与主串第i个字符比较,以便不丢失可能的匹配。

上面讲解的next函数表的定义,然后下面是求next函数表的代码以及实现kmp算法。篇幅有点长,转到下一篇讲。

 

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/TchChan/article/details/82429420
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞