/*
KMP算法核心之next数组
设字符串数组为ch[n],对应的next数组为next[n]
1、则必有next[0]=-1(此时数组ch和next的开始下标都为0)或者
next[1]=0(此时数组ch和next的开始下标都为0)
以及next[2]=1;
2、当i>=2时,判断ch[i]和ch[j]是否相等,
1)若相等,则有next[++i] = ++j;
2)若不相等,则j=next[j],然后重新开始ch[i]和ch[j]的匹配
整个算法过程中一定有i>=j
算法实现如下:(综合考虑了王道数据结构(P266)和天勤数据结构(P99))
*/
void get_next(char T[], int next[])
{
int i = 1, j = 0; //或者 int i = 0 ,j = -1 ;
next[1] = 0; //或者next[0]=-1
while (i < T[0]) //T[0]中保存的是数组T[]的长度
{
if (0 == j || T[i] == T[j])
{
next[++i] = ++j;
}
else
{
j = next[j];/*j只会取大于等于0的数,不用担心j=next[0]=-1的情况,因为j=0根本就不
会进入else语句中,进入else语句中的一定是 j>0 的情况*/
}
}
}
/************************************************************************/
/*KMP算法实现核心:主串只会向右移动,模式串才有可能回溯,
KMP算法在形式上与简单的模式串匹配算法很相似,不同之处在于仅仅当匹配过程中产生失配时,主串的i指针不变
,模式串的j指针退回到next[j]的位置,然后重新开始匹配主串i指针和模式串j指针。若还是产生失配,j指针继续
回退,直到主串i指针和模式串j指针匹配或者j==0。当主串i指针和模式串j指针匹配时或者j指针为0时,next[++i]
=j++,表示的是应该从主串的第i+1个位置开始匹配了(j=0时,表示的是主串的第i个位置和模式串的第一个字符都不
相等了,所以应该从主串的第i+1个位置开始匹配了)
上代码*/
/************************************************************************/
int KMP(char S[], char T[], int next[],int pos ) // T为模式串,S为主串,next数组为模式串S的next数组
//pos 表示从主串的第pos个字符之后的位置开始进行匹配
{
int i = pos, j = 1;
while (i <= S[0] && j <= T[0]) // 和next数组处一样,S[0]保存的是主串的长度,T[0]保存的是模式串的长度
{
if (0 == j || S[i] == T[j]) //主串i指针处和模式串j指针处匹配或者模式串j指针回溯到0,无法继续回溯了
//则应当匹配主串的第i+1指针处和模式串的第j+1指针处
{
++i;
++j;
}
else
{
j = next[j]; //匹配失效,模式S串回溯
}
}
if (j > T[0])
return i - T[0]; //返回主串第pos位置之后的串和模式串总共匹配的长度
else
return 0;
}