KMP算法

1.KMP算法简单介绍
KMP算法是用来查找某一字符串p在主串s中完整出现的起始位置,除此之外还有Bm算法,Sunday算法,
如果用暴力的方法来做的话就是从字符串s以及p的头部开始查找,当某一位不符合时,从字符串s的下一位以及p的头部重新开始查找。
KMP算法_第1张图片
KMP的思想是不动i,改变j使得p尽量能够移动到有效位置
KMP算法_第2张图片
当字符不匹配时,直接改变j的位置,而不是从j的头部重新开始找。那么重要的就是要求字符串p中每一个字符如果不匹配了,它需要跳到的下一个位置。

2.KMP算法的关键在于求出next[]数组,next数组是个什么东西如果弄懂了KMP算法写起来就非常轻松了,next[j]是指:当j不匹配时,j需要移动到的位置.
那么这个值等于多少,要先讲一下前缀和后缀,前缀是指一个字符串除去最后一个字符所对应的字串集合,后缀是指一个字符串除去第一个字符后所对应的子串集合,如
“aba”:前缀:{a, ab} 后缀:{a,ba},这个值就等于j前面的字符串的前缀后缀的最长相同子缀的长度,对于"abaxxxxxx"来说next[3]=1,就是说在位置3不匹配了的话就移动到位置1即b。
注:为什么这样找出来的位置就是j要移动的位置。。。很简单,当位置j不匹配时,需要找的是从头开始的某一字串与j-1所结尾的某一字串相等的结尾位置。所以要用前缀后缀的最大子缀长度。

3.数组next求解过程

    void getNext(int *next, string needle)
    {
        int k = -1;
        int j = 0;
        next[0] = -1; // next[0]表示第0的位置不匹配,此时返回-1表示需要移动 i
        while(j < needle.length() - 1) // 遍历数组,对于每一个位置j,对j+1位置的next值求解,
        {
            if(k == -1 || needle[k] == needle[j]) // 如果位置k与位置j的字符匹配,那么如果在j+1的位置不匹配了,需要移动到k+1的位置上,这里可以进行一个优化,如果k+1位置上的字符与j+1位置上的字符匹配,那么当j+1要移动时,移动到k+1的位置上也时白费力气,那么next[j+1]应该等于next[k+1].
                next[++j] = ++k;
            else
                k = next[k]; // 如果k与j位置的字符不相等了,我们需要找到一个位置使得p[k] == p[j],怎么找呢,就需要运用之前计算出的next数组,让k跑到next[k]的位置
        }
    }

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