网上有很多的KMP算法,写得也很好。
KMP的核心就是next数组的求法和含义。
只要搞懂了next数组, 那理解KMP就只是分分钟的事情。
附上B站的一个外国大佬讲的KMP,很好理解。
看一遍不懂再看第二遍,讲的很好。
KMP常用来求主串的子串中是否出现了模式串,或者出现了几次,或者出现的首位置。
其实关于next的应用还有很多,下面说下用next数组求循环节。(首先需要完全彻底理解next数组)
假设主串str的长度为len,且str存在最小循环节,循环节的长度L为len-next[len],子串为str[0…L-1]。
(1)如果len可以被len - next[len]整除,则表明字符串S可以完全由循环节循环组成,循环周期T=len/L。
(2)如果不能,说明还需要再添加几个字母才能补全。需要补的个数是循环个数L-len%L 。
借鉴网上的一个next数组的例子
对于主串abcdabc
如:abcdabc
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
char | a | b | c | d | a | b | C |
|
next | -1 | 0 | 0 | 0 | 0 | 1 | 2 | 3 |
如对于a,ab,abc,abcd,很明显,前缀和后缀相同的长度为0
对于长度为5的子串abcda,前缀的a和后缀的a相同,长度为1
对于长度为6的子串abcdab,前缀的ab和后缀的ab相同,长度为2
1.无重叠
主串: abcabc(最后的c的下标为5)
next[ 6 ] = 3; 且 len = 6, L = len - next[ 6 ] , len能整除L, 所以主串的循环节为3..
2.重叠
主串:abababab
next[ 8 ] = 6; L = len - next[ len ] = 2; len % L == 0; 所以主串的循环节为2.
3.差元素
主串abcdabc
next[ 7 ] = 3; L = len - next[ len ] = 4; len % L != 0; 所以需要添加几个元素; 需要添加的个数为 add = L - len % L = 1。