| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 10472 人关注过本帖
标题:KMP算法求教
只看楼主 加入收藏
心动音符
Rank: 1
等 级:禁止访问
威 望:1
帖 子:832
专家分:0
注 册:2005-9-15
收藏
 问题点数:0 回复次数:31 
KMP算法求教
前辈们能不能把KMP算法用比较通俗点的语言解释一下啊 书上写的太“数学”了,看的有点晕。最好举个例子。感激感激啊
搜索更多相关主题的帖子: KMP 算法 
2006-07-08 11:30
乌鸦丘比特
Rank: 1
等 级:新手上路
威 望:2
帖 子:625
专家分:0
注 册:2004-7-19
收藏
得分:0 
KMP我当时看了N个解释也不明白,最后是背代码后觉悟的.
所以我的建议是去看代码.

我喜欢创造,一只扑腾着翅膀向天空飞翔的乌鸦
2006-07-08 13:07
心动音符
Rank: 1
等 级:禁止访问
威 望:1
帖 子:832
专家分:0
注 册:2005-9-15
收藏
得分:0 

你有KMP的代码吗 传上来啊 我书上的都是模板的伪代码 看的我发晕,发几个上来啊


2006-07-08 15:51
starrysky
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:华中科技大学EI -T0405
等 级:版主
威 望:11
帖 子:602
专家分:1
注 册:2005-9-12
收藏
得分:0 
以下是引用心动音符在2006-7-8 11:30:05的发言:
前辈们能不能把KMP算法用比较通俗点的语言解释一下啊 书上写的太“数学”了,看的有点晕。最好举个例子。感激感激啊

先别管伪码原代码,你得先弄懂KMP的思想原理,即KMP是干什么用的,为什么要这样。
例子什么的明天给你举个,今天恐怕不行了。
PS:电脑慢的要命,连个编译器都没有,郁闷。。。。。


我的征途是星辰大海
2006-07-12 21:27
starrysky
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:华中科技大学EI -T0405
等 级:版主
威 望:11
帖 子:602
专家分:1
注 册:2005-9-12
收藏
得分:0 

我们从一个普通的串的模式匹配算法开始讲起,这样你才能更深入的了解KMP算法及其优点。
咱们先来看看普通的串的模式匹配算法是怎么进行比较的

主串 (S) a b a b c a b c a c b a b
子串 (T)a b c a c (子串又被称为模式串)

红色表示当前这趟比较指针所在位置,兰色表示当前这趟比较中匹配的部分

第一趟(详细过程)

a b a b c a b c a c b a b
a b c a c


a b a b c a b c a c b a b
a b c a c


a b a b c a b c a c b a b
a b c a c
遇到不匹配的地方时指针回朔,子串向前移动一位(下同),变成如下形式

a b a b c a b c a c b a b
a b c a c

第二趟(省略了中间阶段指针移动比较过程,下同)

a b a b c a b c a c b a b
a b c a c

第三趟

a b a b c a b c a c b a b
a b c a
c

第四趟

a b a b c a b c a c b a b
a b c a c

第五趟

a b a b c a b c a c b a b
a b c a c

第六趟

a b a b c a b c a c b a b
a b c a c _
完成匹配,跳出

这就是普通算法的详细匹配过程,看明白了算法就简单了
详细算法我现在就不给了,等以后有时间再编辑。不过假如串的长度为m,子串的长度为n的话,那么这个算法在最坏的情况下的时间复杂度为O(m*n) ,有没有办法降低它的时间复杂度呢?(废话,当然有拉,不然回这个帖子干什么
拜D.E.Knuth 和 J.H.Morris 和 V.R.Pratt 所赐,我们有了一种时间复杂度为O(m+n)的算法,为了纪念这3位强人为计算机科学所做的贡献,分别取这3位先生的名字的首写字母K,M,P来命名这个算法,即著名的KMP算法。

我们先不管这个KMP算法是什么,我们先来看看我们能够想到怎样的方法来改进上面的普通算法。

通过观察,我们发现一个问题,如果一个子串,假设为a b c d e f , 兰色的部分与主串匹配, 红色的f 与主串不匹配,那么这个子串最多能往右边移动几位呢?因为子串中的第一个字符 a!=b !=c !=d !=e !=f ,那么主串中与b c d e 匹配的部分肯定和a不匹配而与
f不匹配的那部分无法判断与a是否匹配。因此子串最多向右移动5位, 即a移动到f所在的位置上,再进行判断。

在解决这个问题的同时,我们又发现了一个问题,当这个子串为a b c d a f 时又会如何呢?因为无法判断主串中与a匹配对应的位置开始往后的部分是否与整个子串相匹配,所以子串最多向右移动4位,即a移动到a的位置上,然后再进行判断。

按照这个方法,我们再来看看前面我们举的例子。

第一趟

a b a b c a b c a c b a b
a b c a c

第二趟

a b a b c a b c a c b a b
a b c a c

第三趟

a b a b c a b c a c b a b
a b c a c _
完成匹配,跳出

是不是简单多了呢?这个方法不困难吧,也很容易理解吧。
事实上这就是很多人大叫困难的KMP算法的最基本也是最核心的方法
你现在是不是在想 如果我早生50年,KMP算法就要改名了呢?

当然,强人们的思维比我们严密多了,他们考虑的更完全,比如象 a b c d e a b c ,这种字符串相同的情况,当然这种情况并不比单个字符相同的情况复杂多少。在思想上KMP算法与上面我们讲的方法完全一致,都是要让子串向右移动尽可能远的一段距离来达到降低时间复杂度的目的,但在具体操作上KMP算法与上面的方法又有所不同。他们为子串引入了一个参数next[ j ] ,我们先来讲下next[j] 怎么求:

假设子串为 'p1 p2 p3 p4.......pm '
对于第j个字符,有next[ j ] =
(1) 0 (j=1)
(2) Max{ k | 1<k<j && ' p1...p k-1 ' = ' p j-k+1...p j-1 ' }
(3) 1 其他情况

没有大括号就是不方便。哎,上面的算式是不是把你弄晕了呀?没关系,下面我介绍一种偷懒的方法

我就以

子串 a b a b a a b a b
next[j] 0 1 1 2 3 4 2 3 4

为例 来讲下
next[j] 里面 开头的红色01 是固定格式.

我就以兰色的4 来说明下为什么是4.
与4有关的, 是4所对应的兰色a之前的所有的字符,即紫色的 a b a b a
这个字符串中所有符合匹配条件的字符串如下
a b a b a a b a b a
a a
a b a a b a 最长的匹配字符串(a b a b a本身除外)在这里 ,长度为3, 再加上1,就是4
注意next[ j ]中4 的位置!
next[ j ]中其他位置的数值也可以用同样的方法得出

为什么next[j]开头为固定的01?这个问题不太好回答。
最开头的next[j]是由子串第一个字符前面的字符来决定的,但那不存在,因此第一个next[j]的值为0
第二个next[j]是由第一个字符决定的,由于他是自己与自己比较,一定相等,所以值为1。
这样说可能有点牵强。那么我们来看看下面,可能会明白些,也更加了解next[j]到底是起什么作用的。

子串 a b a b a a b a b
next[j] 0 1 1 2 3 4 2 3 4
匹配子串长度 1 2 3 4 5 6 7 8 9 (对应位置 也可看成是截止到当前字符的子串串长)
最大右移 1 1 2 2 2 2 5 5 5 (当前字符不匹配时,子串最大右移距离)

我们发现,最大右移 + 对应的next[j] = 匹配子串长度,我估计这就是为什么要引入next[ j ] 这个参量,为了方便计算最大右移。不过对于next[j]的官方具体定义我没找到,望高人相告,在下先谢过了。

事实上,KMP算法还是有改进余地的,我们一直都在避免讨论这样一种情况:
a b c d e a
0 1 1 1 1 1
a不匹配时,能向右最大移动几位呢?答案是6位,a 所能移动到的位置为a的下一位,即a 的右边一位
而根据next[j]计算出子串最大右移为6-1=5。这里他将a移动到a的位置上,然后做了一次无意义的比较(a = a ,a 与主串不匹配,那么显然a 与主串也不匹配)。这个问题我就不说了,虽然我有个改进方法,但这个问题还是留给大家去思考吧。

至此,关于KMP算法的讲解就到此为止了,如果你还没弄明白KMP是什么,我就没办法了。什么?没给出算法?自己翻书去,我把比算法还重要的东西都给出来了,算法还不是小意思
我相信即使你现在还没明白KMP 是怎么回事(什么?你还没明白?), 结合书上的算法,你也会很快明白的。

[此贴子已经被作者于2006-7-14 15:43:48编辑过]


我的征途是星辰大海
2006-07-13 11:16
starrysky
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:华中科技大学EI -T0405
等 级:版主
威 望:11
帖 子:602
专家分:1
注 册:2005-9-12
收藏
得分:0 
热情 和 SunShine 过来帮忙看看有没有什么错误,漏洞

上面提到的算法以后有时间再补。


我的征途是星辰大海
2006-07-13 17:02
心动音符
Rank: 1
等 级:禁止访问
威 望:1
帖 子:832
专家分:0
注 册:2005-9-15
收藏
得分:0 
哦 谢谢版主啊 虽然看的不是很懂 但是还是很有帮助的

2006-07-13 22:07
心动音符
Rank: 1
等 级:禁止访问
威 望:1
帖 子:832
专家分:0
注 册:2005-9-15
收藏
得分:0 

斑竹你好
我现在手上的是本 清华大学的数据结构(C++版)的是殷人昆编的以我目前的情况不知道适合不适合我啊


2006-07-14 08:14
心动音符
Rank: 1
等 级:禁止访问
威 望:1
帖 子:832
专家分:0
注 册:2005-9-15
收藏
得分:0 

第一趟
a b a b c a b c a c b a b
a b c a c

第二趟
a b a b c a b c a c b a b
a b c a c

第三趟
a b a b c a b c a c b a b
a b c a c 这趟为什么不从b开始啊而从a开始呢,上趟不从哪里不匹配从哪里开始吗?
完成匹配,跳出


2006-07-14 09:52
心动音符
Rank: 1
等 级:禁止访问
威 望:1
帖 子:832
专家分:0
注 册:2005-9-15
收藏
得分:0 
[求助]sd

假设子串为 'p1 p2 p3 p4.......pm '
对于第j个字符,有next[ j ] =
(1) 0 (j=1)
(2) Max{ k | 1<k<j && ' p1...p k-1 ' = ' p j-k+1...p j-1 ' }
(3) 1 其他情况

没有大括号就是不方便。哎,上面的算式是不是把你弄晕了呀?没关系,下面我介绍一种偷懒的方法


我就以

子串 a b a b a a b a b
next[j] 0 1 1 2 3 4 2 3 4 /*这里得数字代表什么啊next[j]得作用是什么啊*/

为例 来讲下
next[j] 里面 开头的红色01 是固定格式.

我就以兰色的4 来说明下为什么是4.
与4有关的, 是4所对应的兰色a之前的所有的字符,即紫色的 a b a b a
这个字符串中所有符合匹配条件的字符串如下
a b a b a a b a b a
a a
a b a a b a 最长的匹配字符串(a b a b a本身除外)在这里 ,长度为3, 再加上1,就是4了
注意next[ j ]中4 的位置!
next[ j ]中其他位置的数值也可以用同样的方法得出

为什么next[j]开头为固定的01?这个问题不太好回答。
最开头的next[j]是由子串第一个字符前面的字符来决定的,但那不存在,因此第一个next[j]的值为0
第二个next[j]是由第一个字符决定的,由于他是自己与自己比较,一定相等,所以值为1。
这样说可能有点牵强。那么我们来看看下面,可能会明白些,也更加了解next[j]到底是起什么作用的。

子串 a b a b a a b a b
next[j] 0 1 1 2 3 4 2 3 4
匹配子串长度 1 2 3 4 5 6 7 8 9 (对应位置 也可看成是截止到当前字符的子串串长)
最大右移 1 1 2 2 2 2 5 5 5 (当前字符不匹配时,子串最大右移距离)

我们发现,最大右移 + 对应的next[j] = 匹配子串长度,我估计这就是为什么要引入next[ j ] 这个参量,为了方便计算最大右移。不过对于next[j]的官方具体定义我没找到,望高人相告,在下先谢过了。

事实上,KMP算法还是有改进余地的,我们一直都在避免讨论这样一种情况:
a b c d e a
0 1 1 1 1 1
当a不匹配时,能向右最大移动几位呢?答案是6位,a 所能移动到的位置为a的下一位,即a 的右边一位
而根据next[j]计算出子串最大右移为6-1=5。这里他将a移动到a的位置上,然后做了一次无意义的比较(a = a ,a 与主串不匹配,那么显然a 与主串也不匹配)。这个问题我就不说了,虽然我有个改进方法,但这个问题还是留给大家去思考吧。

这一段看得我果然很郁闷啊 看来还是很有差距啊!

[此贴子已经被作者于2006-7-14 10:27:39编辑过]


2006-07-14 10:25
快速回复:KMP算法求教
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017940 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved