KMP算法的理解
串的模式匹配,BF算法,采用了穷举法进行匹配。每次匹配不成功都需要回溯,模式串与目标串均需要回溯。
例:
模式串:12112
目标串:12121211121121
模式串相对目标串进行匹配!
一、KMP算法
进行串的模式匹配,KMP算法相对采用穷举法进行模式匹配,消除了主串指针的回溯,提高了算法效率。
二、KMP算法匹配例图
KMP算法:消除主串的回溯,利用模式串的前缀表进行移动,根据模式串的前缀后缀相同,模式串的前缀和对应主串匹配的子串后缀对应,减少匹配次数。
三、实现代码
//获取初始前缀表:
private static int[] getPrefixTable(int[] prefixTable, char[] charArray) {
int length = 0;//最大公共前后缀长度
prefixTable[0] = 0;//前后缀数组第一个默认为0,首元素自身不算前后缀相同
int index = 1;//数组下标
/*
* 前后缀数组的首元素的下标默认为0,即初始从第二个与第一个比较
* 例:12112
* 1、 1 2
* 2、 1 1
* 3、 2 1
* 4、 1 1
* 5、 2 2
* */
while(index<charArray.length){
if(charArray[index]==charArray[length]){
length++;
prefixTable[index] = length;
index++;
}else{
if(length>0){
length--;//回到上一位
}
prefixTable[index] =length;
index++;
}
}
return prefixTable;
}
// 2.重置前缀表:
//所有元素后移一位,首元素置为零。
//应注意,数组长度与下标的关系,相差1。
private static void moveEletment(int[] prefixTable) {
int length = prefixTable.length;
for(int i = 1; i<prefixTable.length;i++){
prefixTable[length-i] = prefixTable[length-i-1];
}
prefixTable[0] = -1;
}
// 3.串匹配
/**
*
* @param charArray 模式串
* @param charArray1 目标串
* @param prefixTable 前缀数组
*/
public static void patternMatch(char[] charArray, char[] charArray1, int[] prefixTable) {
int i = 0;//做模式串的移动下标
int j = 0;//做目标串的移动下标
while(j<charArray1.length){
if(i == charArray.length-1 && charArray[i]==charArray1[j]){
System.out.println("匹配成功开始下标:"+(j-i));//j-i,表示匹配成功后的起始下标
i = prefixTable[i];//匹配成功后,继续往后匹配
}
if(charArray[i]==charArray1[j]){
i++;
j++;
}else{
//不相等,移动子串(根据前后缀表对应的值进行移动对齐)
i = prefixTable[i];
if(i ==-1){
i++;
j++;
}
}
}
}
public static void main(String[] args) {
String str = "12121";
char[] charArray = str.toCharArray();
String str1 = "121211212121";
char[] charArray1 = str1.toCharArray();
int[] prefixTable = new int[charArray.length];
prefixTable = getPrefixTable(prefixTable,charArray);
moveEletment(prefixTable);
patternMatch(charArray,charArray1,prefixTable);
}
总结
模式串与目标串匹配,匹配不成功时,查看匹配成功目标串的子串对应的模式串的前缀表值。进行模式串的前缀与子串的后缀对应,减少匹配的次数。在匹配的过程中,目标串消除了回溯,提高了算法效率。