KMP算法 求next数组的原理
来源:互联网 发布:火线精英免费刷枪软件 编辑:程序博客网 时间:2024/05/03 17:52
在kmp算法中,最难理解的那部分就是next数组的求解原理,今天看懂了一点点,现在记录一下
下标0123................56789..............值abac................abad .............. k2k1 k jj+1
我们假设有这么一个字符串(模式串):abac......abab.......
为方便起见,我们用数组 S 称呼这个字符串
下标0123................56789..............值abac................abab .............. k1 k jj+1
如上图所示,我们可以知道:当 j=8 的时候,next[j]=3(因为S[0]S[1]S[2] = S[5]S[6]S[7]),现在我们来求next[j+1]
- 如果S[k] = S[j],即S[3] = S[8], 那么 next[9] = next[j+1] = next[j] + 1 = k + 1 = 4
- 如果S[k] != S[j],即如上图所示的S[3] != S[8],那该怎么办呢? 下面着重讨论这个问题
由表格中的数据我们可知,由于S[k] != S[j],所以next[j+1]不可能为k+1这么简单,也就是说 next[j+1] 的长度不可能比 next[j] 再长了,所以我们只能寻找更短的相同前后缀
现在我们让 k1 = next[k](本来在代码中应该是:k = next[k],从而构成一个循环,但这里为了方便描述故而采用 k1 的说法,千万不要被误导),由于 k = 3,所以新的 k1 = next[3] = 1(前提是 next[k] 真的有相同的前后缀)(因为S[0] = S[2]),下面重点来了:
因为 S[0]S[1]S[2] = S[5]S[6]S[7] , 所以S[2] = S[7], 又因为有 S[0] = S[2],所以 S[0] = S[7],此时如果有S[k1] = S[j],那么就有:S[0]S[k1] = S[7]S[j],那么就可推断出 next[j+1] = next[k] + 1
最后我们发现 S[k1] = S[1] = b,S[j] = S[8] = b, 所以S[k1] = S[j] , 所以next[j+1] = next[k] + 1 ==> next[9] = 2
(2)上面的情况是 S[k1] = S[j],所以才有 next[j+1] = next[k] + 1, 那要是 S[k1] != S[j] 呢?又会是个什么情况
下标0123................56789..............值abac................abad .............. k2k1 k jj+1
如上面表格所示:此时 k1 = 1, j = 8, S[k1] != S[j] 即:b != d, 这个时候我们继续让 k2 = next[k1] = next[1] = 0, 由于S[k2] != S[j], 即:S[0] != S[8], 所以继续让 k3 = next[k2] = next[0] = -1
这个时候 k3 = -1,说明 next[j+1] 没有相同的前后缀,所以我们就让 next[j+1] = 0,并且重新开始计算 next[j+2] 的相同前后缀,对应的代码就是:j++; k++; next[j] = k; (因为 k 自增之后才为0,j 自增刚好用于计算下一个字符的相同前后缀)
说明:我这里只是描述了其中一种情况而已,但是已经足够用来说明next数组的求解原理了,表格中的红色字体部分可以替换成更长的字符序列,都没有任何问题,因为原理都是一样的
下面是KMP算法的完整代码:
/** * KMP算法 * @param source 源字符串 * @param target 模式字符串 * @return 匹配到的第一个下标 */ public static int kmp(String source, String target) { char[] s = source.toCharArray(); char[] t = target.toCharArray(); //计算next数组 int[] next = getNext(target); int i = 0, j = 0; while (i < s.length && j < t.length) { if (j == -1 || s[i] == t[j]) { i++; j++; } else { j = next[j]; } } // 匹配成功,返回第一个匹配到的下标,否则返回-1 if (j == t.length) { return i - j; } return -1; } /** * 计算next数组 * @param target 模式串 * @return next数组 */ public static int[] getNext(String target) { char[] t = target.toCharArray(); int[] next = new int[t.length]; //需要单独给next[0]赋值为-1,因为后面的循环最多只能给next[1]赋值,无法循环到next[0] next[0] = -1; int j = 0, k = -1; while (j < t.length - 1) { if (k == -1 || t[j] == t[k]) { j++; k++; next[j] = k; } else { k = next[k]; } } return next; }
0 0
- KMP算法 求next数组的原理
- KMP算法求next数组的方法
- KMP算法的next数组计算原理
- KMP算法求next数组
- [学习笔记] KMP算法的Next数组怎么求
- KMP算法求next数组的一些理解
- KMP算法中怎么求next数组
- 使用KMP算法求next数组
- KMP算法的next数组
- KMP算法之NEXT数组原理分析
- kmp求next数组值的方法
- KMP算法之求next 的值
- KMP算法求next数组和nextval数组
- KMP 算法 next数组
- KMP算法--next数组
- KMP算法+NEXT数组
- KMP算法next数组
- KMP算法求next数组和nextval数组的简单方法
- w3school XHTML 教程
- 为任务关键型Java应用优化垃圾回收
- 模型映射库Mantle,高效ios程序员都应该使用
- 盛大弗格森的风范
- 秋季最滋补食物有哪些
- KMP算法 求next数组的原理
- 秋季最滋补食物有哪些
- Android SDK 更新失败解决 Failed to fetch URL https://dl-ssl.google.com/android/repository/repository-6.xml
- fullcalender 中文语言包
- 秋季最滋补食物有哪些
- COM线程模型 - STA接口 - Part II -(跨线程传递对象,消息循环)
- Effective C++之3 资源管理
- 秋季最滋补食物有哪些
- C/C++程序员是这样理解内存的