有人对next函数的递推算法只是处于会敲的状态但是却不理解,下面我来解释一下next函数递推算法的原理
在讲next函数递推算法的之前我们先回顾一下kmp算法的总体
int kmp(char *t char *p)//t是主传,p是匹配串
{
i=1 ; j=1 ;
while( i<=strlen(t)&&j<=strlen(p) )
{
if( j==0 || t[ i ]==p[ j ] ){ i++; j++; }//如果相等或者j=0就令指针向前进一个,否则就利用next函数来返回字母继续与之比较
else j =next[ j ];
}
if( i>strlen(p) )
return i - strlen(p) ;
else return 0;
}
如果你想问,为什么要这么求,解释一下,next 函数值是有意义的,他是代表最大的前缀等于最大后缀,这样求出之后,就可以遍历所有解的可能,你可能想说,怎么会遍历所有的解,它的定义就是最大的前缀,因为和后缀相等了,所以不用,比其他的直接开始比这个就好了,因为这个保证了,超出这个大前缀肯定没有解!
言归正传,怎么求next 也是kmp算法的难点。
因为next的值和主串无关,所以我们一般假设出来next [ j ]= k,然后递推出来next[ j+1 ](好像两者没有因果关系=。=)
思考步骤
我们假设出来一个状态
若p[ j ]==p[ k ]
则next[ j+1 ]=k+1;
若 p[ j ]!=p[ k ]
则开始判断p[next[ k ] ]是否等于p[ j ]
若相等next[ j+1 ]=next[ k ]+1;
如不相等则开始判断p[next[next[ k ] ]是否与p[ j ]相等 依次类推
为什么要这样算?
当我们p[ j ] !=p[ j ]的时候,我们用手算的方法就是从t 以后继续查找(有人也许要问为什么不是往前查找,想一下,如果往前查找能找到的话,那么说明,原来的k并不是最大的不是吗?)从t往后查找最大后缀的过程不是很像0~k查找最大后缀的过程吗?所以将这个状态转移到0~k查找最大后缀的过程了。
在写next函数之前,我们要先声明一下,next函数究竟干什么用的,next 函数是指原来的自变量(就是next里的值)与主串失配后,主串的指针不动,那个匹配串会滑到因变量的地方。
void next_(char *s)
{
next[ 1 ]=0,j=0,i=1;
while( i<=strlen(p))
{
if(j==0||s[ i ]==s[ j ]){ i++; j++;next[ i] =j;}
else next[ j ]=j;
}
}根据递推的思想,我们求出了,next 的指,但是,我们看这个匹配串‘aaab’和主串‘aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab’在i=4失配后,j会先等于4然后等于3然后等于2......但是我们看到j=0,1,2,3都是一个字母‘a’所以这些步骤都是多余的,所以我们应该设置个条件,就是如果返回的那个字母与原来没返回的那个字母是同一个字母的话,那么就直接按失配来处理直接取那个返回值得next值
void next_(char *p,int *next)
{
next[0]=-1;
int j=-1,i=0;
while( i<strlen(p)-1)
{
if(j==-1||p[i]==p[j])
{
i++;
j++;
if(p[i]==p[j] )
next[i]=next[ j ];
else
next[i]= j;
}
else j=next[j];
}
}
本文详细解释了KMP算法中的next函数递推算法原理,通过假设和递推方式阐述如何计算next值。当主串与匹配串失配时,next函数用于确定匹配串的滑动位置,避免冗余比较。通过分析最大前缀等于最大后缀的性质,解释了为何采用这种计算方法。

1896

被折叠的 条评论
为什么被折叠?



