算法复习-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)); } }