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算法,只有在解 ...
随机推荐
- Centos yum 安装mysql报错 No package mysql-server available.
这是因为大多数mysql-*的资源名称被mariadb-*重命名了 所以换成 yum install mariadb-server 就可以了 PS[摘自网络] MariaDB不仅仅是Mysql的一个替 ...
- kill -QUIT <pid>
On Solaris and Linux a thread dump is also printed if the J2SE process receives a QUIT signal. So ki ...
- Beautiful Subarrays
Beautiful Subarrays time limit per test 3 seconds memory limit per test 512 megabytes input standard ...
- android脚步---UI界面修改,关于activity中增加按钮和监听
增加按钮和监听,这个和上个不同在于,它不是在一个dialog里面,而是从新写了一个activity,因此需要先找到这个activity的入口. case R.id.checkframe: if (mC ...
- ida调试 android so
C:\Documents and Settings\Administrator>adb shellshell@htc_v2_dtg:/ $ susushell@htc_v2_dtg:/ # cd ...
- Qt5:无边框窗口拖动
在窗口程序中,无边框窗口程序一般需要特殊处理才能拖动 Qt中,要实现无边框窗口的拖动,需要重新实现 mousePressEvent 和 mouseMoveEvent 俩虚函数 void Widget: ...
- 深入浅出Ajax(二)
<script type="text/javascript"> window.onload = initPage; function initPage() { var ...
- 5个简单的步骤把 WordPress 打造成 CMS
可能网站的首页一直是一成不变的博客样子,有时候也会挺闷的,个人觉得首页就是应该把博客中最好最重要的内容展现给读者,基于这个想法,我们可以把博客的首页改成一个非常简单的 CMS 首页. 基于 WordP ...
- 用Java开源项目JOONE实现人工智能编程
http://www.robotsky.com/ZhiN/MoS/2011-08-25/13142461416649.html 用Java开源项目JOONE实现人工智能编程 https://sourc ...
- Android SystemProperties设置/取得系统属性的用法总结
通过调查得知,Android系统中取得/设置系统属性的用法参考以下3篇文章就足够了. 1.Android SystemProperties简介 介绍了设置属性需要的权限,已经设置权限的方法. Syst ...