KMP字符串匹配算法的分析实现

KMP算法中的next数组构造是一个关键问题,但是博主发现next数组的构造方法有很多,不同的算法实现中构造出的next数组也有所不同,有些方法实在是晦涩难懂。【经典算法】——KMP,深入讲解next数组的求解,这篇博客提供了一种比较简明的理解和构造next数组的方法。引入最长部分匹配长度的概念,实质上就是字符串的前缀(去掉首字符)和后缀(去掉尾字符)相同的最大长度:

  • “A”的前缀和后缀都为空集,共有元素的长度为0;

  • “AB”的前缀为[A],后缀为[B],共有元素的长度为0;

  • “ABC”的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;

  • “ABCD”的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

  • “ABCDA”的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为”A”,长度为1;

  • “ABCDAB”的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为”AB”,长度为2;

  • “ABCDABD”的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

(我们称被匹配的串为源串string source, 作为要匹配对象的串为模式串string pattern)

next[i]实质上就是模式串中从串起始到第i个字符为止的最长部分匹配长度。当我们用next数组做匹配时如果有nof个字符匹配成功,即patter[nof]匹配失败时, 查看next[nof],表示此字符前有next[nof]个字符和模式串起始的next[nof]个字符是匹配的,故只需要把源串当前比较字符继续与pattern[next[nof]]比较即可。

构造next数组时,next[0]=0没有意义,next[0]=0必然,每次根据next[i]计算next[i+1],如果pattern[i]与pattern[next[i]]相等next[i+1]=next[i]+1,否则就像匹配时一样向前迭代查找。

void buildNext(string s, int next[])
{
    int sLength = s.length();

    next[0] = 0; next[1] = 0;
    int nof;//number of fits 
    for(int i=1; i<sLength; i++)
    {
        nof = next[i];//当前匹配字符数,即是s[i]前有nof个字符的最长前缀
        //下一个字符是否匹配
        while(s[i]!=s[nof] && nof!=0)
            nof = next[nof];

        if(s[i]!=s[nof]) next[i+1] = 0;
        else next[i+1] = nof+1;
    }
}

这样实现的匹配算法比较简明, 设置nof使代码清晰有条理。外循环就表示源串待匹配字符指针的移动。循环内部实质上就执行三个操作:1.根据next数组设置nof。2.判断当前字符是否匹配(如果匹配nof当然要+1)3.判断匹配是否结束

//返回第一次匹配成功时在源串中的起始位置
int KMPMapping(string s, string p)
{
    if(p.length()==0 || s.length()==0)
        return -1;
    int *next = new int[p.length()];
    buildNext(p, next);
    int i = 0, j = 0, nof = 0;
    for(int i=0; i<s.length();i++)
    {
        //next[nof]表示匹配nof个字符之后p[nof](因为s0开始)匹配失败时的最长前缀字符数,之s[i]要与p[next[nof]]比较
        while(nof>0 && p[nof] != s[i])
            nof = next[nof];

        //表示当前有nof个字符匹配
        if(p[nof] == s[i])
            nof++;

        if(nof == p.length())
            return i - p.length() + 1;
    }

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