关于KMP学习笔记//2019/7/26
网上一堆“形象”博客浪费我一堆时间,果然以前摸的鱼现在还得还QAQ
我来讲我对于KMP算法的自己理解
为什么网上博客写的xie
首先声明一下,KMP算法最关键的地方不在于匹配,而在于求模式串的最长匹配前后缀,
在网上的其他博客上,这个“最长匹配前后缀”的名字被替换成了“nxt”,而导致博客十分的“好懂”
wdnmd我怎么知道nxt是什么
想一想求一个字符串最长匹配前后缀的最差复杂度是多少?$O(n)$?
是$O(n^2)$啊带哥,枚举长度$O(n)$,判断是否匹配$O(n)$,简直烂到爆
而KMP算法是求出一个字符串$\S$,以位置$\i$为尾的最长匹配前后缀$(1<=i<=strlen(S))$
复杂度难以置信的是$\O(nlogn)$,肥肠优秀,而且不是很难学
KMP求最长匹配前后缀
KMP最关键代码如下
//b[i]是模式串,nxt数组就是最长匹配前后缀长度
void make_nxt(){
int j=0;
for(int i=2;i<=lenb;i++){
while(b[j+1] != b[i] && j>0) j=nxt[j];
if(b[j+1] == b[i]) nxt[i] = ++j;
else nxt[i] = 0;
}
return ;
}
一边看一边说,主要的是,j是当前位的最长匹配前后缀长度,将j维护好之后,赋值给nxt就好
现在的问题就是怎么维护j了,
刚开始到达这一位的时候,j是上一位的最长匹配前后缀中前缀尾的位置,
如果b[j+1] == b[i],即上一位的再往后走一位仍然匹配,那么直接这一位的最长匹配前后缀的长度就是上一位+1,
如果失配,那么该怎么办?仔细想想,j当前所在的位置的最长匹配前后缀的前缀尾是不是可以作为下一次尝试地点?
为什么?因为是匹配前后缀,所以缩回去到前缀的位置时,前缀以前的肯定全都匹配,我们只要看下一位匹不匹配就行了。
啊,世界明朗。
不怎么重要的适配部分
我咕了,这部分您自己推一推吧,或者去康康其他博客,上面看懂了这里比划一下就出来了
KMP求前后匹配的奇怪使用方式
有些题让我们求两个字符串的最长匹配前后缀,我们可以把两个字符串拼在一起,然后跑一个KMP
注意两个字符串拼接时中间要插1个奇怪不同字符来把字符串隔离,防止出锅(一个就行,思考前后缀的匹配方式)
TAG : SIN_XIII