单模式匹配算法-KMP算法
2012-07-22 01:09
309 查看
模式匹配,一般分为单模式匹配和多模式匹配。当然,通常都是指在字符序列中的匹配问题。
单模式匹配,对一个较长的字符序列,调用一次算法只匹配一个模式串。
本文展示的是单模式匹配中的经典算法--KMP算法。
KMP算法是一种高效的模式匹配算法,复杂度可以达到O(m+n),而普通模式匹配算法的复杂度为O(m*n)。
在普通匹配算法中子串与模式串都需要回溯,但这些回溯不是必要的。因为当某一位发生失配时,可以根据已匹配的结果进行判断。这个时候,会产生一个问题:当模式串中的第k位与主串的第i位比较时发生不匹配时,需要将模式串向右滑动到哪里继续与主串的第i位进行比较?如果解决了这个问题,就避免了不必要的主串回溯,减少了模式串回溯的位数,从而使算法复杂度提升到O(m+n)。
KMP算法通过分析模式串,构建next数组,来辅助定位每次模式串向右滑动的位置。具体怎样理解,网上解释的文章非常多,大家可以百度一下,你就知道了。
下面展示一下具体实现的Java代码,供大家讨论。
当然了,对于一次匹配一个模式串,并且,匹配过程中,字符序列不必回退,模式串有限回退,上述算法还是很可行的。
用例的代码,我没有写上来,因为,根据意思,应该很好理解我的用意。对于一个字符串中,如果只需要首次匹配成功的位置,那就不需要Handler了。但是,如果一个字符序列存在多个模式串在里面,那你就要使用Handler了,每次匹配成功的时候,算法都会回调里面的onMatch方法。你只要实现这个StringHandler接口就可以了。
之后是字节序列的模式匹配,虽然用的不多,但是,算法还是一样滴。
是不是有些启发?可以再写写Reader的Matcher,或者InputStream的Matcher ?有时间的朋友可以实现一下,反正算法都是一样的嘛。
单模式匹配,对一个较长的字符序列,调用一次算法只匹配一个模式串。
本文展示的是单模式匹配中的经典算法--KMP算法。
KMP算法是一种高效的模式匹配算法,复杂度可以达到O(m+n),而普通模式匹配算法的复杂度为O(m*n)。
在普通匹配算法中子串与模式串都需要回溯,但这些回溯不是必要的。因为当某一位发生失配时,可以根据已匹配的结果进行判断。这个时候,会产生一个问题:当模式串中的第k位与主串的第i位比较时发生不匹配时,需要将模式串向右滑动到哪里继续与主串的第i位进行比较?如果解决了这个问题,就避免了不必要的主串回溯,减少了模式串回溯的位数,从而使算法复杂度提升到O(m+n)。
KMP算法通过分析模式串,构建next数组,来辅助定位每次模式串向右滑动的位置。具体怎样理解,网上解释的文章非常多,大家可以百度一下,你就知道了。
下面展示一下具体实现的Java代码,供大家讨论。
package houlei.support.matcher; /** * 单模式匹配算法(KMP算法)的匹配器。匹配字符串。 * <p> * 创建时间: 2012-7-22 上午00:52:49 * </p> * @author 侯磊 * @since 1.0 * @version 1.0 */ public class KMPStringMatcher { /** * 当模式串匹配成功时,回调该接口方法。 */ public interface StringHandler{ void onMatch(int index,String str,String pattern); } static int[] getNext(char[] pattern){ int next [] = new int[pattern.length]; next[0] = -1; int j=0,k=-1; while(j<pattern.length-1){ if(k==-1 || pattern[j]==pattern[k]){ j++;k++; next[j] = k; }else{ k = next[k]; } } return next; } /** * 字符数组的匹配。 * @param data 待匹配的数据 * @param pattern 模式串的字符数组 * @return 失配返回<code>-1</code>,首次匹配成功时,返回模式串的位置。 */ public static int match(char[] data,char[] pattern){ int[]next = getNext(pattern); for(int i=0,j=0;i<data.length;){ if(j==-1 || data[i]==pattern[j]){ i++;j++; }else{ j = next[j]; } if(j==pattern.length){ return i-pattern.length; } } return -1; } /** * 字符串的匹配。 * @param data 待匹配的数据 * @param pattern 模式串 * @return 失配返回<code>-1</code>,首次匹配成功时,返回模式串的位置。 */ public static int match(String data,String pattern){ return match(data.toCharArray(), pattern.toCharArray()); } /** * 字符串的匹配。当模式串匹配成功时,回调{@link StringHandler#onMatch(int, String, String)}接口方法。 * @param data 待匹配的数据 * @param pattern 模式串 * @param handler 处理器对象 */ public static void match(String data, String pattern, StringHandler handler) { char[] string = data.toCharArray(); char[] pChars = pattern.toCharArray(); int[]next = getNext(pChars); for(int i=0,j=0;i<string.length;){ if(j==-1 || string[i]==pChars[j]){ i++;j++; }else{ j = next[j]; } if(j==pChars.length){ handler.onMatch(i-pChars.length, data, pattern); j = next[--j];--i; } } } }
当然了,对于一次匹配一个模式串,并且,匹配过程中,字符序列不必回退,模式串有限回退,上述算法还是很可行的。
用例的代码,我没有写上来,因为,根据意思,应该很好理解我的用意。对于一个字符串中,如果只需要首次匹配成功的位置,那就不需要Handler了。但是,如果一个字符序列存在多个模式串在里面,那你就要使用Handler了,每次匹配成功的时候,算法都会回调里面的onMatch方法。你只要实现这个StringHandler接口就可以了。
之后是字节序列的模式匹配,虽然用的不多,但是,算法还是一样滴。
package houlei.support.matcher; public class KMPBytesMatcher { public interface BytesHandler{ void onMatch(int index,byte[]data,byte[]pattern); } static int[] getNext(byte[] pattern){ int next [] = new int[pattern.length]; next[0] = -1; int j=0,k=-1; while(j<pattern.length-1){ if(k==-1 || pattern[j]==pattern[k]){ j++;k++; next[j] = k; }else{ k = next[k]; } } return next; } public static int match(byte[] data,byte[] pattern){ int[]next = getNext(pattern); for(int i=0,j=0;i<data.length;){ if(j==-1 || data[i]==pattern[j]){ i++;j++; }else{ j = next[j]; } if(j==pattern.length){ return i-pattern.length; } } return -1; } public static void match(byte[] data,byte[] pattern, BytesHandler handler){ int[]next = getNext(pattern); for(int i=0,j=0;i<data.length;){ if(j==-1 || data[i]==pattern[j]){ i++;j++; }else{ j = next[j]; } if(j==pattern.length){ handler.onMatch(i-pattern.length, data, pattern); j = next[--j];--i; } } } }
是不是有些启发?可以再写写Reader的Matcher,或者InputStream的Matcher ?有时间的朋友可以实现一下,反正算法都是一样的嘛。
相关文章推荐
- 数据结构- 串的模式匹配算法:BF和 KMP算法
- 改进的模式匹配算法——KMP算法
- 改进的模式匹配算法——KMP算法
- 模式匹配算法-KMP算法
- 串的模式匹配算法——KMP算法解析
- 模式串的快速匹配算法,kmp算法,尊重前人成果,创造新未来
- 改进的模式匹配算法——KMP算法
- 改进的模式匹配算法——KMP算法
- 模式匹配算法(蛮力法与KMP算法的比较)
- 串--->串的模式匹配:Brute-Force算法和 KMP算法
- 改进的模式匹配算法——KMP算法
- 改进的模式匹配算法——KMP算法
- 数据结构20:KMP算法(快速模式匹配算法)详解
- 算法:KMP算法实现的模式匹配
- 串的模式匹配算法:BF和 KMP算法
- 深入串的模式匹配算法(普通算法和KMP算法)的详解
- java 中模式匹配算法-KMP算法实例详解
- KMP算法 串的模式匹配算法优秀总结
- 改进的模式匹配算法——KMP算法
- 字符串模式匹配算法之二:KMP算法