KMP

KMP算法是有三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt共同提出的。算法名字是三人的首字母。
KMP算法主要是解决俩个字符串匹配问题。主要优化主串下标回溯。

暴力解法

image.png

对于暴力解法,其实很简单。我们来看图说话
i 用来记录主串位置
j 用来记录匹配串的位置

我们来手动匹配下上图的来个字符串
我们只需要比较i指针指向的字符和j指针指向的字符是否一致。如果一致就都向后移动,如果不一致,如下图:


image.png

A和E不相等,那就把i指针移回第1位(假设下标从0开始),j移动到模式串的第0位,然后又重新开始这个步骤:


image.png

代码

func kmp(tS:String , pS:String) -> Void {
        var i = 0 , j = 0;
        while i < tS.count && j < pS.count {
            if let tC = tS.characterAtIndex(index: i) , let pC = pS.characterAtIndex(index: j) {
                if tC == pC {
                    i += 1
                    j += 1
                }
                else {
                    j = 0
                    i = i - j + 1  //这里相当于移动到之前刚开始的下一位
                }
            }
        }
        
        if j == pS.count {
//             [i - j ,i] 找到啦
        }
    }

KMP解法
改先发的核心就是找到匹配串j需要回退的位置
我们用一个next数组来保存匹配串每个位置的回退坐标。

image.png

case1:
k = -1
next[++j] = ++k

case2:
p[j] = p[k]
next[++j] = ++k

case3:
p[j] != p[k]
k = next[k]

public static int[] getNext(String ps) {

    char[] p = ps.toCharArray();

    int[] next = new int[p.length];

    next[0] = -1;

    int j = 0;

    int k = -1;

    while (j < p.length - 1) {

       if (k == -1 || p[j] == p[k]) {

           if (p[++j] == p[++k]) { // 当两个字符相等时要跳过

              next[j] = next[k];

           } else {

              next[j] = k;

           }

       } else {

           k = next[k];

       }

    }

    return next;

} 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 现在写文章,也是痛点在哪,就写哪?今天的痛点是老是记不住KMP算法。我曾经3次拿下KMP算法。但令人遗憾的是,我又...
    西部小笼包阅读 1,137评论 0 2
  • 今天看了kmp算法,最开始看得特别混乱,最后终于看明白了,想记录一下。https://github.com/hym...
    不会code的程序猿阅读 995评论 0 4
  • 字符串的查找:朴素查找算法和KMP算法 暴力匹配算法与KMP算法(串的匹配) 字符串查找算法BF和KMP 字符串匹...
    passiontim阅读 1,667评论 0 2
  • 什么是KMP  要做一个东西我们先要理解一个东西,KMP是什么,就是我的标题,字符串匹配。就这样讲可能不好理解,这...
    冀望的air阅读 750评论 0 0
  • KMP 算法(Knuth-Morris-Pratt 算法)是一个著名的字符串匹配算法,效率很高,但是确实有点复杂。...
    1挥改oJo阅读 236评论 0 1