本文将教你如何理解KMP算法
前言
KMP算法是一种经典的模板匹配算法,但是可能很多人跟我一样在开始学习的过程中总有一种似懂非懂的感觉,原理大概懂了,代码也很难理解,理解了自己也写不出来。说到底还是原理理解的不透彻,为此,我想通过这篇博客分享我的个人理解。
一、KMP原理——示意图理解
下面我将从一般情况到特殊情况,带你逐步理解KMP算法。
1.一般情况(KMP核心思想)
如上图所示,当主串和子串比较到某个位置的时候发现S[i]≠T[j],而匹配串T中T[1:j-1]存在如图所示的最长共同前缀和后缀abc,那么显然我们可以不移动i,直接将j移动到k的位置。这也是我们next[j]为啥等于最长共同前缀和后缀的长度+1的原因。
但是,如果说T[1:j-1]不存在共同的前缀和后缀,那又应该怎么办呢?
2.不存在共同的前缀和后缀的情况
如图所示,T[1:j-1]不存在共同的前缀和后缀,那么就只需要让j=1,即next[j]==1,然后继续往下比较。
但是,问题又来了,如果j本身就为1呢,这时你不能在继续让它等于1吧!
3.j=1且S[i]≠T[j]的情况
显然,这时候的做法应该是移动i指针而j指针不动。但为了实现更加方便,我们让j指向0,然后当j==0的时候,i和j同时后移。故next[1] = 0。
到这里基本上把KMP的原理讲完了,但是我们如果回到一般情况,我们考虑如果T[j] = T[next[j]],那又会发生什么?
4.KMP算法优化——T[next[j]]=T[j]
如图所示,即本来应该让j移动到k的位置,但是你都知道了T[j]=T[k],那显然你移动过去再比较T[k]和S[i]肯定也是不相等。因此我们可以更进一步,直接让next[j] = next[k],即直接让它移动到它最后该到达的地方。
二、KMP代码实现(C语言)
1.KMP函数
int KMP(char* S,