关于next算法代码解析(自我见解恭请斧正)

蓝天之隐 2019-05-13 09:07:55
对于正常的字符串模式匹配,主串长度为m,子串为n,时间复杂度会到达O(m*n),而如果用KMP算法,复杂度将会减少线型时间O(m+n)。   设主串为ptr="ababaaababaa";,要比较的子串为a=“aab”;   KMP算法用到了next数组,然后利用next数组的值来提高匹配速度,我首先讲一下next数组怎么求,之后再讲匹配方式。   next数组详解 首先是理解KMP算法的第一个难关是next数组每个值的确定,这个问题困恼我很长时间,尤其是对照着代码一行一行分析,很容易把自己绕进去。 定义一串字符串 ptr = "ababaaababaa";   next[i](i从1开始算)代表着,除去第i个数,在一个字符串里面从第一个数到第(i-1)字符串前缀与后缀最长重复的个数。   什么是前缀? 在“aba”中,前缀就是“ab”,除去最后一个字符的剩余字符串。 同理可以理解后缀。除去第一个字符的后面全部的字符串。   在“aba”中,前缀是“ab”,后缀是“ba”,那么两者最长的子串就是“a”; 在“ababa”中,前缀是“abab”,后缀是“baba”,二者最长重复子串是“aba”; 在“abcabcdabc”中,前缀是“abcabcdab”,后缀是“bcabcdabc”,二者最长重复的子串是“abc”;   这里有一点要注意,前缀必须要从头开始算,后缀要从最后一个数开始算,中间截一段相同字符串是不行的。   再回到next[i]的定义,对于字符串ptr = "ababaaababaa"; next[1] = -1,代表着除了第一个元素,之前前缀后缀最长的重复子串,这里是空 ,即"",没有,我们记为-1,代表空。(0代表1位相同,1代表两位相同,依次累加)。 next[2] = -1,即“a”,没有前缀与后缀,故最长重复的子串是空,值为-1; next[3] = -1,即“ab”,前缀是“a”,后缀是“b”,最长重复的子串“”; next[4] = 1,即"aba",前缀是“ab”,后缀是“ba”,最长重复的子串“a”;next数组里面就是最长重复子串字符串的个数 next[5] = 2,即"abab",前缀是“aba”,后缀是“bab”,最长重复的子串“ab”; next[6] = 3,即"ababa",前缀是“abab”,后缀是“baba”,最长重复的子串“aba”; next[7] = 1,即"ababaa",前缀是“ababa”,后缀是“babaa”,最长重复的子串“a”; next[8] = 1,即"ababaaa",前缀是“ababaa”,后缀是“babaaa”,最长重复的子串“a”; next[9] = 2,即"ababaaab",前缀是“ababaaa”,后缀是“babaaab”,最长重复的子串“ab”; next[10] = 3,即"ababaaaba",前缀是“ababaaab”,后缀是“babaaaba”,最长重复的子串“aba”; next[11] = 4,即"ababaaabab",前缀是“ababaaaba”,后缀是“babaaabab”,最长重复的子串“abab”; next[12] = 5,即"ababaaababa",前缀是“ababaaabab”,后缀是“babaaaababa”,最长重复的子串“ababa”;   还有另外一种方法,我看的有的书上写着: 这里我们定义next[1] = 0 , next[1] = 1;   再分析ptr字符串,ptr = "ababaaababaa"; 跟上一个的情况类似,   next[1] = 0 ,事先定义好的 next[2] = 1 ,事先定义好的 next[3] = 1 ,最长重复的子串“”;1代表没有重复,2代表有一个字符重复。 next[4] = 2 ,最长重复的子串“a”;追偿的长度加1,即为2. next[5] = 3 ,以下都跟之前的一样,这种方法是最长的长度再加上一就可以了。 next[6] = 4 next[7] = 2 next[8] = 2 next[9] = 3 next[10] = 4 next[11] = 5 next[12] = 6   以上是next数组的详细解释。next数组求值 是比较麻烦的,剩下的匹配方式就很简单了。
...全文
68 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧