KMP实现
package com.algorithm.search; import java.util.Random; public final class KMP { private final char[] value; private final int count; public KMP(String str){ value = str.toCharArray(); count = value.length; } /** * 计算模式串匹配失败时,需要移动到的位置 * @param pattern * @return */ private int[] buildNext(char[] source){ int[] next = new int[source.length]; next[0] = 0; for(int i = 1; i < source.length; i++){ int k = 0; int start = 0; int end = i - 1; while(end > 0 && source[start++] == source[end--]) k++; next[i] = k; } return next; } public int indexOf(String pattern){ char[] target = pattern.toCharArray(); int[] next = buildNext(target); int end = target.length -1; int sourceMax = count - target.length; //主串最大移动到该位置,剩下不够模式串的长度 int sourceOffset = 0; int targetOffset = 0; while(sourceOffset <= sourceMax){ while(sourceOffset <= sourceMax && target[targetOffset] != value[sourceOffset]){ sourceOffset++; } while (target[++targetOffset] == value[++sourceOffset]) { if(targetOffset == end){ return sourceOffset - end; } } targetOffset = next[targetOffset]; } return -1; } public static void main(String[] args){ for (int i = 0; i < 3; i++){ String sourceString = getString(10000000); String pattern = getString(200); KMP kmp = new KMP(sourceString); long start = System.currentTimeMillis(); int index = kmp.indexOf(pattern); System.out.println("KMP find:" + index); System.out.println("KMP耗时:" + (System.currentTimeMillis() - start) + "ms"); long start2 = System.currentTimeMillis(); int index2 = sourceString.indexOf(pattern); System.out.println("JDK find:" + index); System.out.println("JDK BF耗时:" + (System.currentTimeMillis() - start2) + "ms"); System.out.println("************************"); } } private static String getString(int max){ String table = "-abcdefghijklmnopqrstuvwxyz"; StringBuilder sb = new StringBuilder(); Random random = new Random(); for (int i = 0; i < max; i++){ int index = random.nextInt(27); sb.append(table.charAt(index)); //sb.append("ababcabcacbab"); } return sb.toString(); } }
测试结果
KMP find:-1
KMP耗时:78ms
JDK find:-1
JDK BF耗时:32ms
************************
KMP find:-1
KMP耗时:78ms
JDK find:-1
JDK BF耗时:31ms
************************
KMP find:-1
KMP耗时:62ms
JDK find:-1
JDK BF耗时:47ms
************************
实际情况并不是所想的KMP算法就一定快,模式串小的话,BF回朔的距离并不远,模式串长的话,KMP在建立next数组相应也要花更长的时间
KMP针对特定的字符串格式才能体现效率