KMP算法解析(转自图灵社区)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP算法解析(转自图灵社区)相关的知识,希望对你有一定的参考价值。
KMP算法是一个很精妙的字符串算法,个人认为这个算法十分符合编程美学:十分简洁,而又极难理解。笔者算法学的很烂,所以接触到这个算法的时候也是一头雾水,去网上看各种帖子,发现写着各种KMP算法详解的转载帖子上面基本都会附上一句:“我也看的头晕”——这种诉苦声一片的错觉仿佛人生苦旅中找到知音,让我几乎放弃了这个算法的理解,准备把它直接记在脑海里了事。
但是后来在背了忘忘了背的反复过程中发现一个真理:任何对于算法的直接记忆都是徒劳无功的,基本上忘得比记的要快。后来看到刘未鹏先生的这篇文章:知其所以然(三):为什么算法这么难?才知道不去理解,而硬生生的背诵算法是多么困难的一件事情。因此我尽可能的尝试理解KMP的算法,并用自己的语言描述一下这个优雅算法的思维过程。
1. 明确问题
我们首先要明确,我们要做的事情是什么:给定字符串M和N(M.length >= N.length),请找出N在M中出现的匹配位置。说白了,就是一个简单的字符串匹配。或许你会说这项工作没什么难度啊,其实只要从头开始比较两个字符串对应字符相等与否,不相等就再从M的下一位开始比较就好了么。是的,这就是一个传统的思路,总结起来其思想如下:
- 当
m[j] === n[i]
时,i与j同时+1; - 当
m[j] !== n[i]
时,j回溯到j-i+1,i回溯到0,然后回到第一步; - 当
i === len(n)
时,说明匹配完成,输出一个匹配位置,之后回到第二步,查找下一个匹配点。
我们举个例子来演示一下这个比较的方法,给定字串M - abcdabcdabcde,找出N - abcde这个字符串。传统思路解法如下:
i: 0 1 2 3 4 5 6 7 8 9 0 1 2
M: a b c d a b c d a b c d e
N: a b c d e // 匹配四位成功后发现a、e不匹配
i: 0 1 2 3 4 5 6 7 8 9 0 1 2
M: a b c d a b c d a b c d e
N: a b c d e // 发现 a、b不匹配
i: 0 1 2 3 4 5 6 7 8 9 0 1 2
M: a b c d a b c d a b c d e
N: a b c d e // 发现 a、c不匹配
i: 0 1 2 3 4 5 6 7 8 9 0 1 2
M: a b c d a b c d a b c d e
N: a b c d e // 发现 a、d不匹配
i: 0 1 2 3 4 5 6 7 8 9 0 1 2
M: a b c d a b c d a b c d e
N: a b c d e // 匹配四位成功后发现a、e不匹配
i: 0 1 2 3 4 5 6 7 8 9 0 1 2
M: a b c d a b c d a b c d e
N: a b c d e // 发现 a、b不匹配
i: 0 1 2 3 4 5 6 7 8 9 0 1 2
M: a b c d a b c d a b c d e
N: a b c d e // 发现 a、c不匹配
i: 0 1 2 3