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)