KMP算法学习
kmp算法完成的任务是:给定两个字符串O和f,长度分别为n和m,判断f是否在O中出现,如果出现则返回出现的位置。常规方法是遍历a的每一个位置,然后从该位置开始和b进行匹配,但是这种方法的复杂度是O(nm)。kmp算法通过一个O(m)的预处理,使匹配的复杂度降为O(n+m)。
参考链接:【经典算法】——KMP,深入讲解next数组的求解 - c_cloud - 博客园
讲解的非常清楚明白
主要就是next数组的求解
KMP算法的核心所在,就是next数组的求解!不过,在这里我找到了一个全新的理解方法!如果你懂的上面我写的的,那么下面的内容你只需稍微思考一下就行了!
跟刚才一样,我用一句话来阐述一下next数组的求解方法,其实也就是两个字:
继承
a、当前面字符的前一个字符的对称程度为0的时候,只要将当前字符与子串第一个字符进行比较。这个很好理解啊,前面都是0,说明都不对称了,如果多加了一个字符,要对称的话最多是当前的和第一个对称。比如agcta这个里面t的是0,那么后面的a的对称程度只需要看它是不是等于第一个字符a了。
b、按照这个推理,我们就可以总结一个规律,不仅前面是0呀,如果前面一个字符的next值是1,那么我们就把当前字符与子串第二个字符进行比较,因为前面的是1,说明前面的字符已经和第一个相等了,如果这个又与第二个相等了,说明对称程度就是2了。有两个字符对称了。比如上面agctag,倒数第二个a的next是1,说明它和第一个a对称了,接着我们就把最后一个g与第二个g比较,又相等,自然对称成都就累加了,就是2了。
c、按照上面的推理,如果一直相等,就一直累加,可以一直推啊,推到这里应该一点难度都没有吧,如果你觉得有难度说明我写的太失败了。
当然不可能会那么顺利让我们一直对称下去,如果遇到下一个不相等了,那么说明不能继承前面的对称性了,这种情况只能说明没有那么多对称了,但是不能说明一点对称性都没有,所以遇到这种情况就要重新来考虑,这个也是难点所在。
如果蓝色的部分相同,则当前next数组的值为上一个next的值加一,如果不相同,就是我们下面要说的!
如果不相同,用一句话来说,就是:
从前面来找子前后缀
1、如果要存在对称性,那么对称程度肯定比前面这个的对称程度小,所以要找个更小的对称,这个不用解释了吧,如果大那么就继承前面的对称性了。
2、要找更小的对称,必然在对称内部还存在子对称,而且这个必须紧接着在子对称之后。
如果看不懂,那么看一下图吧!
说了这么多,下面是代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
void cal_next( char * str, int * next, int len )
{
int i, j;
next[0] = -1;
for( i = 1; i < len; i++ )
{
j = next[ i - 1 ];
while( str[ j + 1 ] != str[ i ] && ( j >= 0 ) )
{
j = next[ j ];
}
if( str[ i ] == str[ j + 1 ] )
{
next[ i ] = j + 1;
}
else
{
next[ i ] = -1;
}
}
}
int KMP( char * str, int slen, char * ptr, int plen, int * next )
{
int s_i = 0, p_i = 0;
while( s_i < slen && p_i < plen )
{
if( str[ s_i ] == ptr[ p_i ] )
{
s_i++;
p_i++;
}
else
{
if( p_i == 0 )
{
s_i++;
}
else
{
p_i = next[ p_i - 1 ] + 1;
}
}
}
return ( p_i == plen ) ? ( s_i - plen ) : -1;
}
int main()
{
char str[ N ] = {0};
char ptr[ N ] = {0};
int slen, plen;
int next[ N ];
while( scanf( "%s%s", str, ptr ) )
{
slen = strlen( str );
plen = strlen( ptr );
cal_next( ptr, next, plen );
printf( "%d\n", KMP( str, slen, ptr, plen, next ) );
}
return 0;
}
参考链接
如果你看不懂KMP算法,那就看一看这篇文章( 绝对原创,绝对通俗易懂) - Stay Hungry,Stay Foolish - 博客频道 - CSDN.NET
KMP算法学习的更多相关文章
- 字符串匹配算法——KMP算法学习
KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...
- KMP 算法 学习 整理
我自己整理的KMP算法的PDF文件:http://pan.baidu.com/s/1o8yKIi2提取密码:8291 别的就不多说啥了,感谢来自海子 博客园的 资料--
- KMP算法学习(详解)
kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法.不过由于其难以理解,所以在很长的一段时间内一直没有搞懂.虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚.在此,综合网上比较好 ...
- 字符串匹配的BF算法和KMP算法学习
引言:关于字符串 字符串(string):是由0或多个字符组成的有限序列.一般写作`s = "123456..."`.s这里是主串,其中的一部分就是子串. 其实,对于字符串大小关系 ...
- kmp算法学习 与 传参试验(常回来看看)
之前在codeforces上做了一道类似KMP的题目,但由于之前没有好好掌握,现在又基本忘记,并没能解答.下面是对KMP算法的一点小总结. 首先KMP算法的核心是纸在匹配过程中,利用模式串的前后缀来加 ...
- KMP 算法学习
KMP算法是用来做字符串匹配的.关于字符串匹配,最简单最容易想到的方法是暴利查找,使用双重for循环处理. 该方法的时间复杂度为O((n-m+1)*m) (n为目标串T长度,m为模式串P长度, 从T中 ...
- KMP算法学习以及小结(好马不吃回头草系列)
首先请允许我对KMP算法的三位创始人Knuth,Morris,Pratt致敬,这三位优秀的算法科学家发明的这种匹配模式可以大大避免重复遍历的情况,从而使得字符串的匹配的速度更快,效率更高. 首先引入对 ...
- KMP算法 学习例题 POJ 3461Oulipo
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 37971 Accepted: 15286 Description The ...
- KMP算法 Next数组详解
题面 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百 ...
随机推荐
- C#GDI+图像处理
支持格式:BMP.GIF.JPEG.EXIF.PNG.TIFF.ICON.WMF.EMF等,几乎涵盖所有常用格式 图像类: Image类:Bitmap和Metafile的类提供功能的抽象基类. Met ...
- phpcms学习的一点心得
最近,在学习phpcms的二次开发,因为要调试搜索模块程序,需建立若干栏目,按照栏目搜索.这一过程中涉及到phpcms的一个概念:模型. 以前并不太注意这个东东. 经过摸索,发现模型其实也是一个栏目的 ...
- Android 如何在Eclipse中查看Android API源码 及 support包源码
当我们阅读android API开发文档时候,上面的每个类,以及类的各个方法都是已经写好的方法和控件,可是我们只是在搬来使用,不知道它的原理,它是如何被实现的.android系统是开源的,所以谷歌官方 ...
- BZOJ4435——[Cerc2015]Juice Junctions
0.题目大意:求两点之间的最小割之和 1.分析:很明显,最小割树,我们发现这个题并不能用n^3的方法来求答案.. 所以我们记录下所有的边,然后把边从大到小排序,然后跑一边类似kruskal的东西,顺便 ...
- Error: failed to fetch platform android
在使用ionic创建项目后,需要添加平台,运行如下命令添加Android平台时: ionic platform add android 1 出现错误: Error: failed to fetch p ...
- Oracle 10G select工作原理
数据库查询语句内部执行过程 select * from table 步骤 分析阶段(parse) 1.共享池库高速缓存有没有该语句.如果有直接返回结果. 2.语法分析sql语句是否正确进行下一步分析 ...
- Genymotion加速下载虚拟镜像速度慢失败Connection timeout
Genymotion也算是个android的模拟程序了, Add new device后下载速度太慢了,容易失败 解决方法有二: 1.设置HTTP代理,在Setting->Network,自己设 ...
- git分支管理策略
http://www.ruanyifeng.com/blog/2012/07/git.html https://www.digitalocean.com/community/tutorials/how ...
- [转]ubuntu 14.04 如何开启和关闭触控板
转自:http://lxn348567248.blog.163.com/blog/static/1201759252014649443513/ 禁用触摸板的命令: sudo rmmod psmous ...
- EXTJS 6 必填项加星号*
/**重写ext filed组件, 实现表单必填项加红色*星号**/ Ext.override(Ext.form.field.Base,{ initComponent:function(){ if(t ...