1.KMP简介
KMP是一个在字符串str中找一个子串pattern的匹配算法,在BF这种暴力匹配算法的基础上改进的。他是有三个人提出来的,所以用三个人的名字来命名这个算法
2.KMP解释
昨天和今天看了好几篇KMP的博客,有个人说的挺好的,坚持下去,就会有柳暗花明的感觉,下面是这位锅锅的博客地址,可以去看看他写的很详细
http://blog.csdn.net/v_july_v/article/details/7041827
我这里也说一下我的理解,做个记录
KMP和BF不同之处在于,i不用回溯到i - j - 1,而j也不用回溯到0这样就提高了算法的效率。
(1)出现str[i]和pattern[j]不匹配值,i不动,j回溯到next[j](next[]存放的就是匹配失败时,j应该回溯到pattern中的位置)
(2)str[i]与pattern[j]匹配时,i++,j++
这里我就不去讨论,为什么j直接跳转到next[j]的位置就okay了。我也不是很理解,这里面有什么前缀后缀,还有些什么之类的...感觉有点懂。其实这里感觉只要理解了怎么计算next[]数组的就okay了
3.next[]数组的计算
next[0] = -1这个是定义好的,不用计算
next[j] = ?呢这个就需要递推关系计算了,如果知道了前next[0,.....j - 1]那计算next[j]就可以看pattern[j] == pattern[k]了(k是pattern中前j个字符串的最大公共子串),
如果相等,则pattern[j] = k + 1;
如果不等,则继续寻找更小的k = next[k],在比较pattern[j] == pattern[k]
可以参考代码,以上解释只为做个记录
1 package com.gxf.kmp; 2 3 public class KmpSear { 4 5 /** 6 * 获取next[]的值 7 * 这里用递推实现 8 * @param pattern 9 * @param next 10 */ 11 public void getNext(String pattern, int next[]){ 12 int k = -1;//最长公共前缀后缀 13 int j = 0; 14 next[0] = -1;//第一个字符的next[]值为-1 15 int length = pattern.length(); 16 17 while(j < length - 1){ 18 if(-1 == k || pattern.charAt(j) == pattern.charAt(k)){//如果相同前缀和后缀长度+1 19 k++; 20 j++; 21 if(pattern.charAt(j) == pattern.charAt(k)){//优化过后的,少一次递推 22 next[j] = next[k]; 23 } 24 else{ 25 next[j] = k; 26 } 27 } 28 else{//如果相同前缀和后缀没有+1,递推找前面最小的相同前缀和后缀 29 k = next[k]; 30 } 31 } 32 } 33 34 /** 35 * 匹配字符串 36 * @param str 37 * @param pattern 38 * @return 39 */ 40 public int kmpSear(String str, String pattern){ 41 int next[] = new int[pattern.length()];//next j的值 42 getNext(pattern, next);//获取next j的值 43 showNext(next); 44 int i = 0;//指向str 45 int j = 0;//指向pattern 46 47 while(i < str.length() && j < pattern.length()){ 48 if(j == -1 || str.charAt(i) == pattern.charAt(j)){ 49 j++; 50 i++;//如果pattern移动到最开始的位置or两个字符刚好相等,同时移动i和j 51 } 52 else{ 53 j = next[j];//匹配失败,获取下一个j的位置 54 } 55 } 56 if(j == pattern.length()){ 57 return i - pattern.length(); 58 } 59 return -1; 60 } 61 62 /** 63 * 输出next[]的内容 64 * @param next 65 */ 66 public void showNext(int next[]){ 67 for(int i = 0; i < next.length; i++){ 68 System.out.print(next[i] + " "); 69 } 70 System.out.println(); 71 } 72 73 /** 74 * 测试程序 75 * @param args 76 */ 77 public static void main(String args[]){ 78 KmpSear kmpSear = new KmpSear(); 79 String str = "substring searching algorithm"; 80 String pattern = "search"; 81 int index = kmpSear.kmpSear(str, pattern); 82 83 System.out.println("index = " + index); 84 } 85 }