KMP算法是有三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt共同提出的。算法名字是三人的首字母。
KMP算法主要是解决俩个字符串匹配问题。主要优化主串下标回溯。
暴力解法
![](https://img.haomeiwen.com/i12326636/4eb81fcc2cac0004.png)
对于暴力解法,其实很简单。我们来看图说话
i 用来记录主串位置
j 用来记录匹配串的位置
我们来手动匹配下上图的来个字符串
我们只需要比较i指针指向的字符和j指针指向的字符是否一致。如果一致就都向后移动,如果不一致,如下图:
![](https://img.haomeiwen.com/i12326636/7977e5ae8b023e59.png)
A和E不相等,那就把i指针移回第1位(假设下标从0开始),j移动到模式串的第0位,然后又重新开始这个步骤:
![](https://img.haomeiwen.com/i12326636/6208f2f6870d65a2.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数组来保存匹配串每个位置的回退坐标。
![](https://img.haomeiwen.com/i12326636/0054f80ef98b8b8d.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;
}
网友评论