KMP算法深入解析
本文主要介绍KMP算法原理。KMP算法是一种高效的字符串匹配算法,通过对源串进行一次遍历即可完成对字符串的匹配。
1、基础知识的铺垫
字符串T的前k(0 =< k <=tlen)个连续的字符串称为T的前缀(假如T的长度为tlen),则当k<tlen时,其前缀称为真前缀。同理,字符串T的后k个连续的字符串称为T的后缀,k<tlen时其后缀称为真后缀。
假如现在有字符串str=”abbaba”。则该字符串的真前缀有:a, ab, abb, abba, abbab. 其真后缀有:a, ba, aba, baba, bbaba。前缀包括源字符串本身,但真前缀不包括,后缀也一样。空字符串是任何字符串的前缀和后缀。
2、前缀函数next的计算
若一个字符串的真前缀等于后缀,我们称它为相等前后缀(为了表达方便,就用相等前后缀表示前后缀相等的前缀,这是本人取得名字,非专业术语)。
前缀函数next的计算就是计算最大相等前后缀的长度。比如字符串p=”ababaca”中,p[3]的最大相等前后缀为ab。next[3]=len(“ab”)=2。对字符串中每个字符计算next就可以得到一个next数组。
那么如何计算next数组呢?假如现在需要计算p[i]的next值,即next[i]。在计算next[i]时,前面的next[0]~next[i-1]已经计算了出来,这时,其计算过程如下:
令k=next[i-1]。若k>0&& p[i]!=p[k]。则k=next[k-1]。因为数组的下标是从0开始的,所以在比较时使用p[i]与p[k] 比较而不是p[k+1],而在重新获取k的值时,使用next[k-1],因为next数组是从0开始的,并且字符串数组也是从0开始计数的,书本上介绍的基本都是从1开始计数的,这是本文与书本之间存在的一点小小区别,但核心思想一样。
关于这点,更通俗的说法是:在计算next[i]时,因为前面的next[i-1]指出了前i-1个字符串的最大相等前后缀。为了计算字符串p[i]的最大相等前后缀的长度,若字符串p[0,1,…, i-1]的最大相等前后缀为p[0,1,…, k-1](k=next[i-1])。此时若p[k]==p[i],则next[i]=k+1。因为这时p[0,1,…, k]==p[i-k, i-k+1, …, i]。
若p[k]!=p[i],为区别起见,我们用q=next[k-1]。如下图所示,此时比较p[i]与p[q]即p[next[k-1]]。因为p[0, 1, .., k-1]==p[i-k, i-k+1,…, i-1],p[0, 1,…, q-1 ] == p[k-q, k-q+1, .., k-1]。若此时p[i] == p[q],则p[i]的最大相等前后缀的长度next[i] = q+1。否则, 如果p[i]!=p[q],则重复此过程,直到q=0。
关于前缀函数的正确性,算法导论有详细的证明,在此略过。
其前缀函数源代码如下:
int *getprefix(char p[])
{
int *h, plen, k, i;
plen = strlen(p);
h = (int *)malloc(plen*sizeof(int));
h[0] = 0;
k=0;
for(i=1; i<plen; i++)
{
while(k>0 && p[k]!=p[i])
k=h[k-1];
if(p[k] == p[i])
k++;
h[i]=k;
}
return h;
}
3、KMP匹配算法的实现
在计算好前缀数组next之后,就可以开始对源字符串进行比对,从源字符串的第0个到最后一个依次进行遍历。这个过程类似计算next数组。只是计算前缀函数的时候是自己与自己进行比较,对每个源串中的字符,若模式串中相应的字符与之不相等,则根据next数组确定模式串中下一个进行比较的字符。
若源串中的字符与模式串中相应的字符相等,则对两个串中的下一个字符进行比较,依次对源串进行一次遍历。
若有模式串匹配成功,则根据next数组将模式串的位置移动指定地方,继续进行比对。
KMP匹配代码如下:
int kmp_matcher(char t[], char p[]) //返回源串中模式串出现的次数
{
int count;
int *h, tlen, plen, i, q;
tlen = strlen(t);
plen = strlen(p);
h = getprefix(p);
count = 0;
q=0;
for(i=0; i<tlen; i++)
{
while(q>0 && t[i]!=p[q])
q = h[q-1];
if(t[i] == p[q])
q++;
if(plen == q)
{
count++;
q = h[q-1];
}
}
return count;
}
KMP算法深入解析的更多相关文章
- 不能更通俗了!KMP算法实现解析
我之前对于KMP算法理解的也不是很到位,如果很长时间不写KMP的话,代码就记不清了,今天刷leetcode的时候突然决定干脆把它彻底总结一下,这样即便以后忘记了也好查看.所以就有了这篇文章. 本文在于 ...
- 【原创】通俗易懂的讲解KMP算法(字符串匹配算法)及代码实现
一.本文简介 本文的目的是简单明了的讲解KMP算法的思想及实现过程. 网上的文章的确有些杂乱,有的过浅,有的太深,希望本文对初学者是非常友好的. 其实KMP算法有一些改良版,这些是在理解KMP核心思想 ...
- KMP算法详解-彻底清楚了(转载+部分原创)
引言 KMP算法指的是字符串模式匹配算法,问题是:在主串T中找到第一次出现完整子串P时的起始位置.该算法是三位大牛:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,以其名字首字 ...
- KMP算法解析(转自图灵社区)
KMP算法是一个很精妙的字符串算法,个人认为这个算法十分符合编程美学:十分简洁,而又极难理解.笔者算法学的很烂,所以接触到这个算法的时候也是一头雾水,去网上看各种帖子,发现写着各种KMP算法详解的转载 ...
- KMP算法解析
介绍一种高效的KMP算法:代码可以直接运行 #include <iostream> #include <iomanip> using namespace std; void p ...
- poj_3461 KMP算法解析
A - Oulipo Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit S ...
- Java数据结构之字符串模式匹配算法---KMP算法
本文主要的思路都是参考http://kb.cnblogs.com/page/176818/ 如有冒犯请告知,多谢. 一.KMP算法 KMP算法可以在O(n+m)的时间数量级上完成串的模式匹配操作,其基 ...
- 字符串匹配的KMP算法详解及C#实现
字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...
- KMP算法具体解释(转)
作者:July. 出处:http://blog.csdn.net/v_JULY_v/. 引记 此前一天,一位MS的朋友邀我一起去与他讨论高速排序,红黑树,字典树,B树.后缀树,包含KMP算法,只有在解 ...
随机推荐
- PHP使用Redis
首先确保安装了Redis扩展 详细的使用方式 请浏览扩展文档 https://github.com/phpredis/phpredis#connection $obj = new Redis(); $ ...
- Redis 密码设置和登录
Redis 一般在生产环境中,大家都不使用密码,为了确保安全,都是在防火墙上对redis端口做IP白名单的 我是个技术控,我非得了解一下密码这回事[虽然以后不会用到,呵呵] 好了,废话不多说,简单介绍 ...
- windows cmd 命令大全
原文: http://www.cnblogs.com/greatverve/archive/2011/12/09/windows-cmd.html 命令简介 cmd是command的缩写.即命令行 . ...
- struts1.x中web.xml文件的配置
1.配置欢迎文件清单 当客户访问Web应用时,如果仅仅给出Web应用的Root URL,没有指定具体的文件名.Web容器会自动调用Web应用的欢迎文件.<welcome-file-li ...
- Diamond Collector
Diamond Collector 题目描述 Bessie the cow, always a fan of shiny objects, has taken up a hobby of mining ...
- .h .m切换
快捷键是:command + control +[↑|↓]
- uboot1.1.6之NOR FLASH 出现的问题解决方法
U-BOOT移植,structure has no member named `CAMDIVN speed.c: In function `get_HCLK':speed.c:114: error: ...
- HTML5 学习01
HTML的英语意思是:Hypertext Marked Language,即超文本标记语言,是一种用来制作超文本文档的简单标记语言. 所谓超文本,是因为它可以加入图片.声音.动画.影视等内容,事实上每 ...
- Win7+QTP10.0+IE9无法启动IE的解决方法
请安装QTP补丁QTP_00626. 更多补丁请查阅:http://www.cnblogs.com/testware/archive/2010/10/13/1849985.html
- [转]Qt5.0 连接 webkit 错误解决
新版的qt5.0把webkit拆分为webkit和webkitwidgets两个部分,所以如果遇到错误: Undefined symbols for architecture x86_64:“QWeb ...