KMP算法(简略的说)

KMP算法(简单的说)

KMP算法的核心就是求解next数组,具体参考http://www.cnblogs.com/10jschen/archive/2012/08/21/2648451.html

package algorithm;
//字符串匹配类
public class StringMatcher {
	
	//朴素字符串匹配,t:要匹配的目标字符串,pattern:匹配的模式字符串
	public static int navieMatch(String t,String pattern){
		int len1 = t.length();
		int len2 = pattern.length();
		for (int i = 0; i <= len1-len2; i++) {
			int j = 0;//每次都设置patter从头开始匹配
			int k = i;//保存当前t的偏移量
			//第一个字符匹配成功,才开始之后的匹配
			while(t.charAt(k++) == pattern.charAt(j++)){
				//匹配成功
				if (j == len2) {
					return i;
				}
			}
		}
		return -1;
	}
	
	//根据模式pattern得到next数组
	public static int[] getNext(String pattern){
		int len = pattern.length();
		int[] next = new int[len];
		//第一个next为0
		next[0] = 0;
		for(int i = 1 ; i < len; i++){
			//k表示之前的对称性
			int k = next[i-1];
			/*
			 *不断递归判断是否子对称 
			 * k等于0时,说明不再存在子对称
			 * pattern[k]不等于pattern[i],说明子对称的后面的一个字符和当前字符不相等,所以继续递推
			 * 这些都不满足直接进行单个字符比较的条件
			 * */
			while (k != 0 && pattern.charAt(k) != pattern.charAt(i)) {
				k = next[k-1];//向前找子对称的子对称
			}
			if( pattern.charAt(i) == pattern.charAt(k))//找到了这个子对称,或者是直接继承了前面的对称性,这两种都在前面的基础上++
	              next[i]=k+1;
	         else
	              next[i]=0;       //如果遍历了所有子对称都无效,说明这个新字符不具有对称性,清0
		}
		return next;
	}
	
	public static int kmpMatch(String t,String pattern){
		int[] next = getNext(pattern);
		int len1 = t.length();
		int len2 = pattern.length();
		for (int i = 0; i <= len1-len2; ) {
			int j = 0;//每次都设置patter从头开始匹配
			int k = i;//保存当前t的偏移量
			//第一个字符匹配成功,才开始之后的匹配
			while(t.charAt(k++) == pattern.charAt(j++)){
				//匹配成功
				if (j == len2) {
					return i;
				}
			}
			i += i - next[i] + 1;
		}
		return -1;
	}
	
	public static void main(String[] args) {
		System.out.println(navieMatch("abcabaabcabac","abaa"));
		int[] next = getNext("ababaca");
		for(int i : next){
			System.out.print(i+" ");
		}
		System.out.println();
		System.out.println(kmpMatch("abcabaabcabac","abaa"));
	}
	
	
	
	
	
}