KMP模式匹配
KMP模式匹配简记
KMP算法是数据结构中,模式匹配的一个经典算法,有些地方比较晦涩难懂,网上的很多教程都不太直观,因此我准备组织自己的口水语言,简单记录一下KMP算法是怎么回事。
依托一个例子来介绍。
抛出例子
举个例子,用字符串,h=“hello”,去匹配字符串,s=“hehehello”,先扔出结果来感受一下:
序号§ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
字符 | h | e | h | e | h | e | l | l | o |
next | -1 | 0 | 0 | 1 | 2 | 3 | 4 | 0 | 0 |
nextVal | -1 | 0 | -1 | 0 | -1 | 0 | 4 | 0 | 0 |
next数组的含义
next数组的含义。这是被匹配的字符串s的相关记录。next[i]表示的含义为,以第i位之前一位字符,作为结尾的一个字符串,与从第0位字符开始,作为开头的字符串,之间能匹配上的长度。从另一个角度理解,就是当h与s,在s的第i位匹配失败时,此时i位前,假设有k位与s从开头开始的k位长度的字符串,已经匹配上,那么这k位,与被匹配的字符串s的最前面k位字符串,自然是已经匹配上了的,也就无需再匹配了,把被匹配字符串s,匹配失败的那一位开始,与匹配字符串h的k位(第k+1个字符),开始匹配即可了。
nextval数组的含义
nextval是在next数组的基础上,让每一步比较更有价值,省去没有意义的步骤。
就是将next往前跳到值得匹配的那一位。如next[5]跳到p[3],也就是“e”这个字符,但是“e”和P[5]的字符串相同,都是“e”,所以已经可知,匹配不上了,这也就没必要浪费一步,不然需要,跳到P[3]先了,再以p[3]的next[3]为跳板,再跳一步,到p[1],此时发现p[1]还是“e”,也就还需要跳一步,到p[0],p[0]为“h”,不同,有比较的价值。
而这中间从p[5]到p[3],再到p[1],这几步其实是多余的,可以省略的,可以直接跳到p[0],因此,nextval的意思,就是把中间这几步省略,直接指向具有比较价值的一步。因此,这个过程即nextval[5]=next[5]=p[0]。
总结
要理解KMP算法,最重要的是理解KMP算法的作用,其实是跳过已经匹配过的部分,让每一步比较更有价值。