KMP算法

串′ababaaababaa′的next数组为:011234223456
先从人的分析角度去分析怎么做。。。。
next数组下标从1开始计算
next[1] 肯定是 0
next[2] 肯定是 1
next[n] 的情况,将前面n-1个字符,计算从首尾开始组成最大的相同子串的长度,如果找到,那么next值是该长度加1,否则next值是1。

举例
next[6]的计算,字符串第六位是 a ,( ababa a ababaa)
将前面的5个字符,从头尾开始取4个组成子串比较,如果不相等,则从首尾取3个字符组成子串继续比较,并以此类推, 如果一直比较到最后一个字符都不相等,那么该next值为1。
4个字符的情况:abab : baba
3个字符的情况:aba : aba 此时相等,那么next[6] = 3+1 = 4

经历过人的分析计算角度来看待,,,不难得到KMP算法的核心就是尽量利用到串可能是局部回文的性质。
或者说,当串具有以下性质 串A = (串1 串2 串1) 时候 当下次串B与它比较时候发生了失配时候,是否每次都要进行从头比较???串B假设是串B = (串1 串3)这样的式子,如果每次失配,B都要从头再来。。不觉得这样是极度浪费吗?所以才引入了Next数组来指引着B下一次比较的位置究竟在哪里。。。。
直接上代码吧。。。

void makeNext(const char P[],int next[])
{
    int q,k;//q:模版字符串下标;k:最大前后缀长度
    int m = strlen(P);//模版字符串长度
    next[0] = 0;//模版字符串的第一个字符的最大前后缀长度为0
    for (q = 1,k = 0; q < m; ++q)//for循环,从第二个字符开始,依次计算每一个字符对应的next值
    {
        while(k > 0 && P[q] != P[k])//递归的求出P[0]···P[q]的最大的相同的前后缀长度k
            k = next[k-1];          //不理解没关系看下面的分析,这个while循环是整段代码的精髓所在,确实不好理解 
        if (P[q] == P[k])//如果相等,那么最大相同前后缀长度加1
        {
            k++;
        }
        next[q] = k;
    }
}

注意:q理解成start k理解成end这样比较好一点。解释一下最难解释的while循环吧。。。。
KMP算法_第1张图片
看图吧。。。。
当在字符t处失配时候,k马上通过k = next[k-1];语句快速索引到k1处,意思是试图证明 证明前面的 (子串1,子串2,子串2结尾+1字符) 和后面的 (子串2,子串1,t)回文。。。
假设相等。。。。退出while循环
假设不等试图证明 证明前面的 (子串1,子串1结尾+1字符) 和后面的 (子串1,t)回文。。。
假设相等,退出while循环。。。。
假设不等,再去循环循环。。。。呃,要是实在不明白,可以画:前面k个子串,后面k个子串然后自己想想,很快就能想明白了,应该。。。。

参考:http://www.cnblogs.com/c-cloud/p/3224788.html

你可能感兴趣的:(算法,KMP)