算法复习-KMP算法

KMP是个字符串匹配算法,是在暴力匹配的基础上进行了优化,一个目标串A和匹配串B,目的是为了在A中匹配到B,根据匹配串构造了一个next数组,减少了匹配串与目标串的次数。当在中第i位与B中的第j位不匹配时,根据next[j]的值,确定B往后挪的位置,目的是为了让B[next[j]]与A[i]进行匹配。

这里有个误区,将B往后挪,并不代表B中B[j-next[j]...j]能继续使用于A[i]到A[i+next[j]],能保证的只有A[i-next[j] ....i-1] 与 B[0...next[j]] 是匹配的。

所以在B[j]处失配时,只能拿B[next[j]] 来与A[i]适配。

public class KMP {
	
	char[] sequence;
	char[] match;
	
	public int[] CountNext(char[] match){
		int i,j,k; 
		char pk,pj;
		int len = match.length;
		int[] next = new int[len];
		next[0] = -1;  //根据设计规则,第0位设为-1
		for(j=0;j<len-1;j++){
			k = next[j];
			if(k == -1){
				next[j+1] = 0;  //第1位设为0,因为next[i]是从相同前后缀长度右移一位得来的,所以第1位为0
				continue;
			}
			pk = match[k];
			pj = match[j];
			if(pk == pj){
				next[j+1] = next[j] +1;
			}
			else{
				k =next[k];
				while(k != -1){ //循环算出next[k],如果不匹配,则k=next[k],直到k = -1,即匹配到第0位,那么说明无前后相同子串,设为0
					pk = match[k];
					if(pk == pj){
						next[j+1] = next[k]+1;
						break;
					}
					k = next[k];
				}
				if(k == -1){
					next[j+1] = 0;
				}
			}
			
		}
		return next;
	}
	
	public int Match(char[] sequence, char[] match){
		
		int[] next = CountNext(match);
		int i=0,j=0,mv;
		char s,m;
		while(i<sequence.length){
			s = sequence[i];
			m = match[j];
			if(j == -1 || s==m ){
				i++;
				j++;
				if(j == match.length){
					return i-match.length;
				}
			}
			else{
				j = next[j]; //将j换为next[j]与sequence[i]来匹配
			}
		}
        return -1; //sequence遍历完了都没匹配上,则返回-1表示匹配失败 } public static void main(String arg[]){ KMP kmp = new KMP(); kmp.match = "ABCDABCE".toCharArray(); kmp.sequence = "ABCEABCDABCE".toCharArray(); System.out.println(kmp.Match(kmp.sequence, kmp.match)); } }

  

posted on 2015-07-19 17:43  zxahu  阅读(131)  评论(0编辑  收藏  举报

导航