前缀函数:
首先是前缀函数,前缀函数并不是只分析前缀,其取值同时兼顾真前缀真后缀的对应
前缀函数next[j]是指某个字符串的最长真后缀同时也是它的前缀的子串长度。
KMP中表示在一次匹配失败后模式串可以往后移动的最大步长。
//T是被匹配的串。
//P是模式串。
//字符串都是从下标1开始的。
void next(char P[])
{
int m=strlen(P+1); //这里是因为要从P[ 1 ]开始输入字符串的
next[1]=0;
for(int k=0,q=2;q<=m;q++)
//这段代码我感觉用通俗的语句说就是k是用来表示子串中前k个和后k个是相同的,
//q是用来遍历数组的需要
{
while(k>0&&P[k+1]!=P[q]) //如果P[k+1]和P[q]中字符不同说明匹配是失败,
//要把k的值重新退到next[ k ],直到两者相同才停止。
//这样做的好处是没必要再重新从头再来,节约时间。
k=next[k];
if(P[k+1]==P[q])
k++;
next[q]=k;
}
}
真前缀,真后缀,后缀:
举个例子,如字符串 abcde
排除空字符,则:
所有的前缀有 a, ab, abc, abcd, abcde
其中真前缀有 a, ab, abc, abcd
可以类比中学阶段集合概念,真子集就是真前缀,空集就是空字符,子集就是所有的前缀
同理,真后缀就是指不包含自身的后缀
理解KMP模式匹配的时候会比较难理解前缀函数 next[j]
a -> 0
ab -> 0
aba -> 1
abab -> 2
ababc -> 0