KMP模式匹配,查找子字符串
Posted 106-cyh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP模式匹配,查找子字符串相关的知识,希望对你有一定的参考价值。
代码解析
void cal_next(char *ptr, int *next, int plen) { next[0] = -1; int k = -1; for (int i = 1; i <= plen-1; i++) { while (k > -1 && ptr[k + 1] != ptr[i]) { k = next[k]; } if (ptr[k + 1] == ptr[i]) { k = k + 1; } next[i] = k; } }
一.void cal_next(char *ptr, int *next, int plen)
1.for(int i=1;i<plen-1;i++);next,next[i];中的i为什么从1开始,plen-1结束?
因为i=1~plen-1,next[0]=-1;
所以数组next即可取遍0~plen-1的元素,长度为plen
2.while(k>-1&&ptr[k+1]!=ptr[i])中的while可以改为if吗?
因为每一次发现不匹配可以向更小的开始匹配,不止是一次
3.k=next[k];
k将变为更小的(小字符串内部的)最大相同前后缀长度,比较时,自然是在原有的基础上变为ptr[k+1]与字符串末端比较,而比较的基础是:前后缀是相同的,即ptr[k+1]接在前缀后,ptr[i]接在后缀后,如果相同,便可以 k++,否则,以此类推,此乃递归思想或者叫数学归纳思想(这两种思想到底有什么区别呢?我也不知道.冒昧地问一下...明白next[k]中下标是k时地含义吗?)
4.next[0]=-1;int k=-1中的两个-1,意义何在?
对于while(k>-1&&ptr[k+1]!=ptr[i])中的k为初值-1,此时k+=0,str[k+1]==str[0];
对于while(k>-1&&ptr[k+1]!=ptr[i])中的k=0时,若ptr[k+1]!=ptr[i],则k=next[k]==-1;又化为初值了,这只有问题中的两个-1同时存在时,才能达到这种效果
5.为什么k>next[k]?
首先要明确,比较的前提是k>-1(不是因为next[-1]不存在,而是因为while(k>-1&&ptr[k+1]!=ptr[i])中有这个条件);其次要明白next[k]中下标是k时的含义:就是在原来的,有前后缀相同的小字符串长度内部,再找一个更小的,有前后缀的,更小字符串的,前后缀想同的长度-1(这里的-1是出于对字符数组的关怀);在这两个的基础上,就有了k>next[k]的本质理解
6.k=next[k]能改为k--吗?
咋一看,问题不大,效率降低了而已,其实,很危险...举个粒子吧:abcd abce abcd abcc
真实匹配为-1,结果却为2;离谱的很,因为它的二次检索不是建立在“小字符串”(前面已经介绍该词的来源了)的基础上
7.该函数实现了什么功能?
宏观来观察一下,你会发现,该函数使用来得到next数组的,这是理解该函数的前提条件;
该数组的含义是,对于字串的不同字符串长度,对应的,前后缀字符串相同的,最长的长度减一(出于对数组下标的尊重,才要减的一)
KMP
int KMP(char *str, int slen, char *ptr, int plen) { int *next = new int[plen]; cal_next(ptr, next, plen); int k = -1; for (int i = 0; i < slen; i++) { while (k >-1&& ptr[k + 1] != str[i]) k = next[k]; if (ptr[k + 1] == str[i]) k = k + 1; if (k == plen-1) return i-plen+1; } return -1; }
二.int KMP(char *str, int slen, char *ptr, int plen)
1.int *next = new int [plen]无需释放?
至于是无需释放还是自动释放,现在自身能力有限,我无法解释,期待你在评论区赐教
2.通过比较两个函数,不同点是?有些虽相同,但功能也有不同的,又是?
1..while(k>-1&&ptr[k+1]!=ptr[i])改为while(k>-1&&ptr[k+1]!=str[i])
.讲母串作为“后缀”去理解,再结合函数cal_next(),问题就迎刃而解了;
2..k=next[k]
.貌似功能不变,其实,也差不多,还是要记住,把母串当作后缀来思考会更省事
3.。if(k==plen-1)
.匹配度达百分之百是,就好了,此处比较简单,不啰嗦了
测试
char *str = "bacbababadababacambabacaddababacasdsd"; char *ptr = "ababaca"; int a = KMP(str, 36, ptr, 7); return 0;
以上是关于KMP模式匹配,查找子字符串的主要内容,如果未能解决你的问题,请参考以下文章