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+ ...
随机推荐
- Error: Could not find or load main class Test
问题描述 Linux 环境下运行 Java 程序时,执行 javac Test.java 生成 Test.class 文件,再执行 java Test 时报错:Error: Could not fin ...
- yagmail 实现发邮件
yagmail 实现发邮件 yagmail 可以更简单的来实现自动发邮件功能. github项目地址: https://github.com/kootenpv/yagmail 安装 pip insta ...
- ansible的Filter
filter的格式: value..| filter() 在python中就是类的实例化 filter(self,*args,**kwargs) self就是filter中管道符前的value. ...
- docker - 容器lxc
容器:是在用户空间进行隔离的组件叫做容器 常用的容器有lxc ----libcontainer---runc 需要隔离的资源有: Rootfs:每个容器对应的一个目录做为根目录 User: Hostn ...
- every循环
一.语法 var result = myArr.every(function(item, index){ return item>0; }) //全部满足,才为true every方法检测数组中 ...
- 使用 Java 将多个文件压缩成一个压缩文件
使用 Java 将多个文件压缩成一个压缩文件 一.内容 ①使用 Java 将多个文件打包压缩成一个压缩文件: ②主要使用 java.io 下的类 二.源代码:ZipMultiFile.java pac ...
- configure: error: Cannot find php-config. Please use --with-php-config=PATH
本文章给大家介绍configure: error: Cannot find php-config. Please use --with-php-config=PATH错误解决办法. configure ...
- 执行Android后台任务的最佳实践
灵活执行后台任务可以帮助提升应用性能,并最小化电量损耗. Android后台任务主题包含以下三个子主题: 1. 在IntentService中执行后台任务: 2. 使用CursorLoader在后台加 ...
- 【JAVA基础】一:聊聊笔试常见到的 “==、equal” 比较是否相等的内在差别
开始本文之前,先让我们记住一个口诀(这个口诀只针对基础的类比如String.Integer等,如果是自定义的类,需要看equal的具体实现): equal比较其值,== 比较地址 这两天在走查代码的时 ...
- XVII Open Cup named after E.V. Pankratiev. GP of Moscow Workshops
A. Centroid Tree 枚举至多两个重心作为根,检查对于每个点是否都满足$2size[x]\leq size[father[x]]$即可. #include<stdio.h> # ...