KMP初步
KMP算法专门用于处理字符串匹配问题。
开始学习的时候觉得很有道理,但是一些细节总觉得有些模糊,所以一直觉得懵懵懂懂。今天思考了一下,总结一下,希望对大家也有帮助。
朴素的字符串匹配算法就是一个一个字符挨个去试,但是当匹配串长度比较长的时候复杂度显然会爆炸。
为了解决这个问题,很厉害的三个人想出来了这个很厉害的算法。
核心思想是假如比较到第j+1个字符的时候匹配失败,不是像朴素算法一样从头开始比较,而是利用匹配串自身的特性直接跳转到匹配串头部,这个头部和尾部相同。这是比较容易理解的,显然这样做是正确的,但是为什么能够保证不会漏掉可能存在的其他匹配串呢?
现在我们用反证法来看这个问题:即假在串s1中查找串s2,如果比较到si的第i个元素,s2的第j个元素,发现s1[i+1]!=s2[j+1],此时我们可以直接跳转到s2[p[j]]处继续匹配s1和s2,p[j]是指s2[1..p[j]]和s2[i-p[j]+1..i]相同的最大p[j],现在证明这样做不会漏掉前面(s1[i-j+1..i-p[j]+1]这些部分是没有进行比较的)可能存在的其他串。
假如在那个区域存在与s2匹配的串,因为长度问题,这个串结束的部分一定超过i,而这个串在i前面的部分和s2[1..j]相同,但是它比最大的p[j]还长,这样的串是不可能存在的,同时也说明了为什么KMP需要最大的p[j]。
现在基本思想已经证明正确,所要做的就是思考如何实现这个算法了。问题主要有两个:如何得到p[j]和如何实现匹配算法。
为了方便理解,这里先介绍如何实现匹配算法:
1 void kmp()
2 {
3 j=0;//匹配串的指针
4 for(int i=0;i<n;i++) //之所以是小于n是因为会判断i+1处的值
5 {
6 while(j>0 && a[i+1]!=b[j+1]) j=p[j];//j>0说明在j前面存在匹配,存在匹配而出现不匹配就要将j指针前移到和末尾相同而且下一位支持匹配的地方
7 if(b[j+1]==a[i+1]) ++j;
8 if(j==m)
9 {
10 printf("%d",i+1-m+1);//直接输出匹配位置
11 j=p[j]; //继续寻找(可重叠)匹配
12 //j=0; 寻找不重叠匹配
13 }
14 }
15 }
这个过程的复杂度为O(n),具体为什么需要进行摊还分析(我也不是太懂。。。)。
然后我们就要考虑如何得到p[j]了。
我们不难发现(不难个鬼哦),在求p[j]的过程其实就是在前j-1个字符中查找第j个位置组成的子串的过程,因此得到p[j]的过程其实和上述过程类似不同之处在于每次查找结束后都要更新那个位置的p[j]的值。
1 void pre()
2 {
3 p[1]=0;
4 j=0; //j指i所匹配的位置
5 for(int i=1;i<m;i++)
6 {
7 while(j>0 && b[j+1]!=b[i+1]) j=p[j];
8 if(b[i+1]==b[j+1]) ++j;
9 p[i+1]=j;
10 }
11 }
大概就是这样,嗯~
KMP初步的更多相关文章
- kmp算法初步理解
123456789 abbdaxnds Next 01212 第三位看第二位b,第二位和第三位相同,都是b,所以第三位的next是第二位的next加1,即1+1=2 第四位看第三位b,第四位d与第 ...
- Number Sequence HDU 1711(KMP)
http://acm.hdu.edu.cn/showproblem.php?pid=1711 首次接触KMP,自己都不是特别理解.在网上百度看了好几个帖子之后,对KMP也有了初步的理解. #inclu ...
- KMP算法中next函数的理解
首先要感谢http://blog.csdn.net/v_july_v/article/details/7041827以及http://blog.chinaunix.net/uid-27164517-i ...
- KMP算法具体解释(转)
作者:July. 出处:http://blog.csdn.net/v_JULY_v/. 引记 此前一天,一位MS的朋友邀我一起去与他讨论高速排序,红黑树,字典树,B树.后缀树,包含KMP算法,只有在解 ...
- 完全掌握KMP算法思想
文档下载页面http://download.csdn.net/detail/yedeqixian/4209500 80页在讲KMP算法的开始先举了个例子,让我们对KMP的基本思想有了最初的认 ...
- KMP字符串匹配 简单理解
http://www.cnblogs.com/c-cloud/p/3224788.html 字符串匹配,长串长度为m,子串长度为n 则,暴力破解的复杂度为o(m*n) 如果用kmp匹配,则复杂度为o( ...
- 字符串匹配(KMP 算法 含代码)
主要是针对字符串的匹配算法进行解说 有关字符串的基本知识 传统的串匹配法 模式匹配的一种改进算法KMP算法 网上一比較易懂的解说 小样例 1计算next 2计算nextval 代码 有关字符串的基本知 ...
- POJ2406 Power Strings —— KMP or 后缀数组 最小循环节
题目链接:https://vjudge.net/problem/POJ-2406 Power Strings Time Limit: 3000MS Memory Limit: 65536K Tot ...
- 移动端之Android开发的几种方式的初步体验
目前越来越多的移动端混合开发方式,下面列举的大多数我都略微的尝试过,就初步的认识写个简单的心得: 开发方式 开发环境 是否需要AndroidSDK 支持跨平台 开发语言&技能 MUI Win+ ...
随机推荐
- linun 乌班图 vim : 依赖: vim-common (= 2:7.3.429-2ubuntu2) 但是 2:7.3.429-2ubuntu2.1 正要被安装
sudo apt-get purge vim-common sudo apt-get updatesudo apt-get upgradesudo apt-get install vim
- Django 序列化-token
幂等性 幂等性:多次操作的结果和一次操作的结果是一样的 ,put请求是幂等的 post请求不是幂等的 序列化组件 全局和局部钩子函数 异常信息抛出过程 认证 路由里的,login.as_view() ...
- kafka_2.11-2.1.0测试
kafka测试启动创建topic ./kafka-topics.sh --create --zookeeper dip005:2181,dip006:2181,dip007 --replication ...
- 初学python之路-day02
python,诞生于1989年的圣诞,Guido van Rossum为了打发无聊,因此发明了python,并且开放了其源代码,使得这门语言在随后的几十年的发展的越来越广.现今,2.x版本已经在2.7 ...
- linux在telnet情况下root登录提示login incorrect
root登录时总是提示 login incorrect SSH可以登录 别的用户也可以通过telnet登录 唯独root不可以 解决方法: vi /etc/pam.d/login # auth r ...
- spring boot 添加拦截器的简单实例(springBoot 2.x版本,添加拦截器,静态资源不可访问解决方法)
spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor 一.HandlerInterceptor HandlerInterceptor是s ...
- django 第四天
简单的一对多的页面 实现的页面结果如下 利用正则匹配 1.x系列和2.x系列django的用法不同,....他x的. 关于正则匹配 我一直没能实现,再试试吧 路由分发,尤其是在多个页面的时候 app0 ...
- RC terms.
ETA: estimated time of arrival DEA: 1-Leg: 2-Leg: FCC: L10N: LocalizatioN i18N: InternationalizatioN ...
- 学习笔记: yield迭代器
yield 与 IEnumerable<T> 结对出现, 可实现按需获取 , 迭代器模式 static void Main(string[] args) { ...
- sklearn交叉验证2-【老鱼学sklearn】
过拟合 过拟合相当于一个人只会读书,却不知如何利用知识进行变通. 相当于他把考试题目背得滚瓜烂熟,但一旦环境稍微有些变化,就死得很惨. 从图形上看,类似下图的最右图: 从数学公式上来看,这个曲线应该是 ...