KMP算法

来源:互联网 发布:node webservice 编辑:程序博客网 时间:2024/06/05 11:07


先看看非KMP的暴力匹配:

//str for string and p for patternString str = "ABCABD";String p = "ABD";for(int i = 0;i < str.length;i ++){int j =0;int first = i;while(str.charAt(i) == p.charAt(j) && j < p.length){i++;j++;}if(j == p.length){//return "found"}else {i = first;j = 0;}}//return "not found";

对以上匹配 每次失配i++ 明知下次失配仍是i++;


KMP的失配移动距离:

kmp则先统计 匹配模式“p”  非前缀部分相对于前缀 的最大重复度,

如: p =“ABCABD” 重复串有AB,则第四个字母A重复最大长度为1,第五个字母B 因为重复串AB 而最大重复长度为2.
这样做的好处是 当 模式串失配时可以根据 失配前的字符 是否重复来选择 i 移动的位数;
而具体到如何计算出移动的位数 则与 失陪前字符 的最大重复长度 有关
如:对于 p =“ABCABD” 每个字符标序 1-6;
4,5的字符‘A’,‘B’ 中B的最大重复长度为2,若 模式p 在匹配到 字符D时 失配(如匹配字符串str = “ABCABE ABCABD”);
5处的B 为字符D的上一个字符,其最大重复长度为2,而p要移动的方式 是将首部的AB 一直移动到4,5的AB所在的位置,这个移动的距离加上 5处B的最大重复长度(3+2)等于当前失配标记j(因为j从0开始)。
因此 i不用i++,而是i = i + 移动的距离 即 i = i + (j - 失配字符上一个字符的 最大重复长度)
检查头部和尾部:
若第一个字符A失配 而A没有上一个字符,
可以选择 ----

1:加个条件判断
2: 改变  失配字符上一个字符的 最大重复长度 这一做法
对于2
 KMP用了 next[] 来代替,next[k]表示 在k - 1处的字符 的最大重复长度 
 i = i + (j - 失配字符上一个字符的 最大重复长度) 则变成了 i = i +(j - next[j]
对于 第一个字符A next[0] = -1,表示 i = i + (j -(-1))
对于第二个字符 next[1] = 0;因为 第一个字符重复长度始终为0;
对最后的字符 通过。


next数组的求法:

若是成千上万的字符串 组成的模式串 是不可能用肉眼求出next
next迭代求法:通过next[i] 求出next[i+1];
如p = “...ABC...”,标序 abc;
若只已知 a处的 A 最大重复长度 为k即next[b] = k,则b处的B其最大重复长度怎么算:
最大重复长度 是和 开头串比较的结果
则可知 p第k-1处 字符也是A
若p第k处的字符同样是B 那么b处的B 其最大重复长度 为k+1 即 c处的C 其next[c] = k+1;
p为模式串

next[0] = -1;next[1] = 0;if(next.length>1){//p is the pattern stringfor(int i = 2; i< next.length; i ++){if(p.charAt(next[i-1]) == p.charAt(i-1)){next[i] = next[i-1] + 1;}else next[i] = 0;}

KMP匹配:

完整代码:

1 0
原创粉丝点击