记录KMP算法,记录其经典之处。。。
2008-07-03 14:30
169 查看
离开学校已经多年了,早已经不再抚弄那些陈旧的书籍。
周末,深圳的天气阴沉,老天这段时间总是很乐意显摆,动不动就给深圳人民来次几十年一遇的暴雨,似乎要把一年的雨水全部在这些天下完似的。
所以呆在家里面看电视,上网,实在也无聊。随手翻开大学时候的(数据结构,还留着啊,当初刚出来的时候总没有底气,总希望能够随时充电用)。看到了字符串的模式匹配一章。突然发现KMP算法是如此的经典。故记之。。。
在提KMP的经典之前,首先要提基本的模式匹配算法:
所谓模式匹配,简单点说就是对两字符串进行匹配,找出一个字符串在另一个字符串中的位置。
基本的模式匹配是这样的:
假设有字符串
S=S1S2......SN(由于为了算法效率的需要,所以一般都把S[0]保存S的长度)
P=P1P2......PM(同上)
其中(M<N),要求返回P在S中出现的位置。
所以算法要点如下:
假设从S中i点开始扫描(也就是从S[i]开始,此时用一个变量k=i),顺序比较S[i]和P[1],S[i+1]和P[2]。这样,当P进行到第j个字符也就是P[j]的时候,发现S[i+j-1]和P[j]不匹配,那么需要把S的指针i回朔到S起始的下一个字符也就是k+1继续比较。
如图:
以上就是模式匹配的基本算法,这种算法对于大多数的匹配来说基本是O(N+M)的时间复杂度。
但是对于如下的字符串:
S=0000000000000000000000000000001
P=000001
这种字符串来说,每次匹配失败都是在P到最后一个字符也就是j=M的时候,此时S的指针又必须回朔,导致大量的匹配。此时的时间复杂度是O(N*M)。
所以基本算法的时间复杂度是O(N*M)。当然了,对于大多数的匹配是不会有这么高的时间复杂度的,所以这种算法现在也在广泛使用,因为简单。
为了解决上述的问题,KMP算法被发现。
KMP算法的思想如下。匹配过程中,出现不匹配时,S的指针不进行回朔(原地不动),将P尽可能地向后移动一定的距离,再进行匹配。
如图:
从上图中我们看到,当S移动到i,P到j的时候失配。这时候i不回朔,而只是将P向前移动尽可能的距离,继续比较。
假设,P向右移动一定距离后,第k个字符P[k]和S[i]进行比较。
此时如上图,当P[j]和S[i]失配后,i不动,将P前移到K,让P[k]和S[i]继续匹配。现在的关键是K的值是多少?
通过上图,我们发现,因为***部分表示已经匹配了的结果(因为是到了S[i]和P[j]的时候才失配,所以Si-j+1Si-j+2…Si-1 = P1P2…Pj-1,见***的部分)。所以有:
1、 Si-k+1Si-k+2…Si-1 = Pj-k+1Pj-k+2…Pj-1。
所以当P前移到K时,有:
2、 Si-k+1Si-k+2…Si-1 = P1P2…Pk-1。
通过1,2有
Pj-k+1Pj-k+2…Pj-1 = P1P2…Pk-1。
呵呵,此时我们的任务就是求这个k值了。。。
理解了这一点之后,终于能够发现此算法的经典了。
周末,深圳的天气阴沉,老天这段时间总是很乐意显摆,动不动就给深圳人民来次几十年一遇的暴雨,似乎要把一年的雨水全部在这些天下完似的。
所以呆在家里面看电视,上网,实在也无聊。随手翻开大学时候的(数据结构,还留着啊,当初刚出来的时候总没有底气,总希望能够随时充电用)。看到了字符串的模式匹配一章。突然发现KMP算法是如此的经典。故记之。。。
在提KMP的经典之前,首先要提基本的模式匹配算法:
所谓模式匹配,简单点说就是对两字符串进行匹配,找出一个字符串在另一个字符串中的位置。
基本的模式匹配是这样的:
假设有字符串
S=S1S2......SN(由于为了算法效率的需要,所以一般都把S[0]保存S的长度)
P=P1P2......PM(同上)
其中(M<N),要求返回P在S中出现的位置。
所以算法要点如下:
假设从S中i点开始扫描(也就是从S[i]开始,此时用一个变量k=i),顺序比较S[i]和P[1],S[i+1]和P[2]。这样,当P进行到第j个字符也就是P[j]的时候,发现S[i+j-1]和P[j]不匹配,那么需要把S的指针i回朔到S起始的下一个字符也就是k+1继续比较。
如图:
以上就是模式匹配的基本算法,这种算法对于大多数的匹配来说基本是O(N+M)的时间复杂度。
但是对于如下的字符串:
S=0000000000000000000000000000001
P=000001
这种字符串来说,每次匹配失败都是在P到最后一个字符也就是j=M的时候,此时S的指针又必须回朔,导致大量的匹配。此时的时间复杂度是O(N*M)。
所以基本算法的时间复杂度是O(N*M)。当然了,对于大多数的匹配是不会有这么高的时间复杂度的,所以这种算法现在也在广泛使用,因为简单。
为了解决上述的问题,KMP算法被发现。
KMP算法的思想如下。匹配过程中,出现不匹配时,S的指针不进行回朔(原地不动),将P尽可能地向后移动一定的距离,再进行匹配。
如图:
从上图中我们看到,当S移动到i,P到j的时候失配。这时候i不回朔,而只是将P向前移动尽可能的距离,继续比较。
假设,P向右移动一定距离后,第k个字符P[k]和S[i]进行比较。
此时如上图,当P[j]和S[i]失配后,i不动,将P前移到K,让P[k]和S[i]继续匹配。现在的关键是K的值是多少?
通过上图,我们发现,因为***部分表示已经匹配了的结果(因为是到了S[i]和P[j]的时候才失配,所以Si-j+1Si-j+2…Si-1 = P1P2…Pj-1,见***的部分)。所以有:
1、 Si-k+1Si-k+2…Si-1 = Pj-k+1Pj-k+2…Pj-1。
所以当P前移到K时,有:
2、 Si-k+1Si-k+2…Si-1 = P1P2…Pk-1。
通过1,2有
Pj-k+1Pj-k+2…Pj-1 = P1P2…Pk-1。
呵呵,此时我们的任务就是求这个k值了。。。
理解了这一点之后,终于能够发现此算法的经典了。
相关文章推荐
- 今天看到一个很经典的递归,存下做个记录
- 转载只为记录经典之<轻量级进程和普通进程以及线程之间的区别>
- 转载只为记录经典之<linux多线程编程>
- 转载只为记录经典之<Linux驱动程序编写演示----编译驱动程序 >
- [转载]最经典,最可怕的qq聊天记录
- 《怦然心动》经典记录
- 读-《c++设计新思维-泛型编程与设计模式之应用》经典记录(英文书名:《modern c++ design》)
- 经典算法研究系列:六、教你初步了解KMP算法、updated
- KMP算法的经典例题(poj 3461、poj 2752、poj 2406、poj1961)
- 读【程序员修炼之道:从小工到专家】书籍的笔记经典记录[未完待续]
- 经典8皇后问题,仅仅做个记录吧
- 转载只为记录经典之<STP协议>
- 转载只为记录经典之<linux驱动简介 >
- KMP算法与一个经典概率问题
- sql 经典语句记录
- SQL Server 2008编程入门经典(第3版) 学习记录2
- 传智博客(JavaWeb方面的所有知识)听课记录(经典)
- 记录经典好看的电影
- QQ聊天记录电子取证经典案例
- 串的模式匹配 经典KMP算法