实现KMP主要是因为其相对于朴素匹配算法效率更高 更加智能 可以大大避免重复遍历的情况
---C语言实现
---通过主串的一次遍历 既可以完成查找
---基本的实现:实现了Nex数组和匹配查找
---改进:实现了Next的反向数组和正向反向双向的匹配查找
KMP基本实现:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int KMPSearch(char SrcString[],int len_src,char MatchString[],int len_match)
{
int count;
int *NextVal;
int LastCharNextValue;
int Src_Search_index;
int Match_Search_index;
int ReturnValue = -1;
if(SrcString == NULL || MatchString == NULL ||len_src <= 0 ||len_match <= 0)return ReturnValue;
//Next数组
NextVal = (int *)malloc(len_match*sizeof(int));
NextVal[0] = 0;//默认匹配串初始位置的NextValue为0
for(count = 1;count < len_match;count++)
{
LastCharNextValue = NextVal[count-1];
if( MatchString[count] == MatchString[LastCharNextValue] )//1
{
NextVal[count] = LastCharNextValue+1;
}
else
{
while(1)
{
if(LastCharNextValue == 0)
{
NextVal[count] = 0;
break;
}
LastCharNextValue = NextVal[LastCharNextValue-1];//使当前位置前移到上次比较的位置重复比较 直到达成1 或比较到首位置
if( MatchString[count] == MatchString[LastCharNextValue] )
{
NextVal[count] = LastCharNextValue+1;
break;
}
}
}
}
//匹配
Src_Search_index = Match_Search_index = 0;
while(Src_Search_index < len_src && Match_Search_index < len_match )
{
if( SrcString[Src_Search_index] == MatchString[Match_Search_index] )//匹配成功后移
{
Src_Search_index++;
Match_Search_index++;
}
else if(Match_Search_index != 0)//匹配失败 前移
{
Match_Search_index = NextVal[Match_Search_index-1];
}
else//匹配失败 前移至首元素 结束前移 从主串下一位置重新匹配
{
Src_Search_index++;
}
}
free(NextVal);
NextVal = NULL;
if(Match_Search_index == len_match)//匹配成功
{
ReturnValue = Src_Search_index-len_match;
}
return ReturnValue;
}
int main()
{
int result;
char *str = "adohfsdahfjfjfhfdghjfdghhsdluirehuiuguihewjejn";
char *seacherstr = "hjfdghhsdlu";
result = KMPSearch(str,strlen(str),seacherstr,strlen(seacherstr));
printf("%d \n",result);
system("pause");
return 0;
}
KMP改进版本:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int KMPSearch(char SrcString[],int len_src,char MatchString[],int len_match)
{
int count;
int *NextVal;
int LastCharNextArrValue;
int Left_Src_Search_index;
int Left_Match_Search_index;
int ReturnValue = -1;
//------------------------------------------------------------------------------------------------------------------------------
int *ResNextVal;
int NextCharNextArrValue;
int ResIndex;
int Right_Src_Search_index;
int Right_Match_Search_index;
int ChangeMoveFlag;
//------------------------------------------------------------------------------------------------------------------------------
if(SrcString == NULL || MatchString == NULL ||len_src <= 0 ||len_match <= 0)return ReturnValue;
//Next数组
NextVal = (int *)malloc(len_match*sizeof(int));
NextVal[0] = 0;//默认匹配串初始位置的NextValue为0
for(count = 1;count < len_match;count++)
{
LastCharNextArrValue = NextVal[count-1];
if( MatchString[count] == MatchString[LastCharNextArrValue] )//1
{
NextVal[count] = LastCharNextArrValue+1;
}
else
{
while(1)
{
if(LastCharNextArrValue == 0)
{
NextVal[count] = 0;
break;
}
LastCharNextArrValue = NextVal[LastCharNextArrValue-1];//使当前位置前移到上次比较的位置重复比较 直到达成1 或比较到首位置
if( MatchString[count] == MatchString[LastCharNextArrValue] )
{
NextVal[count] = LastCharNextArrValue+1;
break;
}
}
}
}
//------------------------------------------------------------------------------------------------------------------------------
//反向Next数组
ResNextVal = (int *)malloc(len_match*sizeof(int));
ResNextVal[0] = 0;//默认匹配串首位置的NextValue为0
for(count = len_match-2;count >= 0;count--)
{
ResIndex = len_match-count-1;
NextCharNextArrValue = ResNextVal[ResIndex-1];
if( MatchString[count] == MatchString[len_match-NextCharNextArrValue-1] )//1
{
ResNextVal[ResIndex] = NextCharNextArrValue+1;
}
else
{
while(1)
{
if(NextCharNextArrValue == 0)
{
ResNextVal[ResIndex] = 0;
break;
}
NextCharNextArrValue = ResNextVal[NextCharNextArrValue-1];//使当前位置前移到上次比较的位置重复比较 直到达成1 或比较到首位置
if( MatchString[count] == MatchString[len_match-NextCharNextArrValue-1] )
{
ResNextVal[ResIndex] = NextCharNextArrValue+1;
break;
}
}
}
}
//------------------------------------------------------------------------------------------------------------------------------
//匹配
ChangeMoveFlag = 0;//0:left 1:right
Left_Src_Search_index = Left_Match_Search_index = 0;
Right_Src_Search_index = len_src-1;
Right_Match_Search_index = len_match-1;
while(Left_Src_Search_index-Right_Src_Search_index <= len_match && Left_Match_Search_index < len_match && Right_Match_Search_index >= 0 && Left_Src_Search_index < len_src && Right_Src_Search_index >= 0)
{
if(ChangeMoveFlag == 0)
{
if( SrcString[Left_Src_Search_index] == MatchString[Left_Match_Search_index] )//匹配成功后移
{
Left_Src_Search_index++;
Left_Match_Search_index++;
ChangeMoveFlag = 1;
}
else if(Left_Match_Search_index != 0)//匹配失败 前移
{
Left_Match_Search_index = NextVal[Left_Match_Search_index-1];
}
else//匹配失败 前移至首元素 结束前移 从主串下一位置重新匹配
{
Left_Src_Search_index++;
ChangeMoveFlag = 1;
}
}
else if(ChangeMoveFlag == 1)
{
if( SrcString[Right_Src_Search_index] == MatchString[Right_Match_Search_index] )//匹配成功后移
{
Right_Src_Search_index--;
Right_Match_Search_index--;
ChangeMoveFlag = 0;
}
else if(Right_Match_Search_index != len_match-1)//匹配失败 前移
{
Right_Match_Search_index = len_match - ResNextVal[len_match-Right_Match_Search_index-1] -1;
}
else//匹配失败 前移至首元素 结束前移 从主串下一位置重新匹配
{
Right_Src_Search_index--;
ChangeMoveFlag = 0;
}
}
}
free(NextVal);
NextVal = NULL;
free(ResNextVal);
ResNextVal = NULL;
if(Left_Match_Search_index == len_match)//匹配成功
{
ReturnValue = Left_Src_Search_index-len_match;
}
else if(Right_Match_Search_index < 0)
{
ReturnValue = Right_Src_Search_index+1;
}
return ReturnValue;
}
int main()
{
int result;
char *str = "dfljkghjkdlhgjkhgjhgkl";
char *seacherstr = "jhgkl";
result = KMPSearch(str,strlen(str),seacherstr,strlen(seacherstr));
printf("%d \n",result);
system("pause");
return 0;
}