KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
示例:
主串S:ababaaababcaa
模式串T:ababc
第一步:
先求出模式串“abcdex”的next数组:
第二步:
开始匹配
两个串的前4个字符完全一样,直到第5个,‘a’与‘c’匹配失败。
此时j不需要回溯到1,而是回溯到next[j]即可。
以此类推,即可获取匹配的结果
KMP算法的实现:
void getNextValue(char* T,int *nextVal, int size_T) //求模式串的next数组并存入nextVal中
{
int i,j;
i = 1; //后缀游标
j = 0; //前缀游标
nextVal[1] = 0;
while(i < size_T)
{
if(j==0 || T[i] == T[j]) //T[i]表示后缀的单个字符,T[j]表示前缀的单个字符
{
++i;
++j;
nextVal[i] = j;
}
else
{
j = nextVal[j]; //前缀与后缀不同,游标j回溯到nextVal[j]的位置,重新与失配的i位置的字符对比
}
}
}
int index_KMP(char* S,char* T,int pos, int size_S, int size_T) //从主字符串S的pos位置开始匹配模式串T
{
int i = pos;
int j = 1;
int *next = new int[size_T];
next[0] = size_T;
getNextValue(T,next, size_T); //获取next数组
while(i<size_S && j<size_T) //开始匹配主串与模式串
{
if(j==0 || S[i]==T[j])
{
i++;
j++;
}
else
{
j = next[j]; //匹配失败,游标j回溯到next[j]的位置,重新与失配的i位置的字符对比
}
}
if(j >= size_T)
{
return i-size_T+1; //匹配成功,返回匹配成功的开始位置
}
else
{
return 0; //匹配失败,返回0
}
}