您的位置:首页 > 其它

KMP算法中的next函数的证明

2013-11-01 21:29 721 查看

KMP算法的next函数的证明

1.1 Next函数定义与代码

1.1.1 定义

1.1.2 实现代码

/*代码摘自《大话数据结构》*/

/*t为字串,next为int数组,存储next值*/

void getnext(string T,int *next)

{

int i,j;

i=1;j=0;next[1]=0;

while(i<T[0]) //T[0]表示字符串T的长度

{

if(j==0 || T[i]==T[j])

{

++i;

++j;

next[i]=j;

}

else

j=next[j];

}

}

1.2 证明思路

采取分段证明的办法,证明j往区间(m,k)移动是不正确的,验证移动到m(next[j]=m)的正确性。

在证明的过程中,都是假设j移动到某个位置之后,讨论if判断条件会成立。因为如果是不成立的话,程序流程又会转移到j的移动,这样我们就会陷入死循环。而且,这种假设,即if成立,在逻辑上也是成立的,就像递归函数一样,只要一层是正确的,递归的肯定也没问题。

1.3 证明

首先观察这个函数的代码,我们可以获得如下信息:

(1) 若if成立,则i、j都加1;

(2) i的值为k,则next[k]已经有了结果,且在下一轮if之前j= next[k];

(3) 当要求next[k]的时候,if中的判断条件是i=k-1;

证明:

前提条件:假设next[k]=s,

即T[1]…[s-1]=T[k-s+1]…[k-1](1)

现求next[k+1]=?根据前面的结论,此时i=k,j=s。令next[s]=m.

现进行if判断:

(1) 若条件成立,

即T[i]=T[j],也即T[k]=T[s],结合式(1),则有

T[1]…[s-1][s]=T[k-s+1]…[k-1][k] (2)

则next[k+1]=s+1,即代码中的next[i]=j;继续下一次if判断。

(2) 若条件不成立,

即T[i] != T[j],则我们需要移动j。

假设向区间 (s , k) 移动,假使使j=s+1,满足if条件,即T[k]=T[s+1],

根据代码,则next[k+1]=s+2,意味着

T[1]…[s-1][s][s+1]=T[k-s]…[k-1][k] (3)

等式两边去掉末位,

T[1]…[s-1][s] =T[k-s]…[k-1] (4)

从这可以推出next[k]=s+1,与前面矛盾,所以j不能向前移(假若向前移动更多位的话,就会推出next[k]比s+1更大的值)

下面证明j向(m,s)区间移动是不行的。

已知条件:i=k,j=s,next(s)=m,next(k)=s,T[k]!=T[s],需证明移动到m+1是不行的。

现我们假设把j移动到m+1,而不是代码中的m。

根据已知条件可以得到:

next(k)=s =>T[1]…[s-1]=T[k-s+1]…[k-1] (5)

next(s)=m =>T[1]…[m-1]=T[s-m+1]…[s-1] (6)

if判断成立,T[k]=T[m+1],则得到next(k+1)=m+2,

T[1]…[m+1]=T[k-m]…[k] (7)

两边去掉右边一位,则有T[1]…[m] =T[k-m]…[k-1] (8)

观察(5),因为s>=m+1,所以k-m>=k-s+1,

所以T[1]…[m] =T[k-m]…[k-1]

= T[s-m]…[s-1] (由5)

从这里可以推出,next(s)至少为m+1,与已知矛盾。

显然,若移动到m+2等就可以得到更大的next(s)的值了。

接下来,我们证明移动j到next[j]的正确性。

设next[j]=m,此时j=s,next[s]=m,移动j到next[s]后,即j=m。

由next[s]=m有:

T[1]…[m-1] =T[s-m+1]…[s-1] (9)

判断T[i]==T[j],即T[k]==T[m],条件成立之后,因为s>=m+1,所以

k-m+1>k-s+1,即T[k-m+1]在T[k-s+1]…[k-1][k]中。

取(1)中等式两边右边的m-1项,得到:

T[s-m+1]…[s-1] =T[(k-1)-(m-1)+1]…[k-1]= T[k-m+1]…[k-1] (10)

又结合(9)(10)有

T[1]…[m-1] =T[k-m+1]…[k-1] (11)

结合T[k]==T[m],有

T[1]…[m-1][m]=T[k-m+1]…[k-1][k] (12)

从而next[k+1]=m+1,即代码中的next[i]=j。由next的定义可知,j向(0,m)区间移动的话就得不到正确的next值,应为已经找到了j=m满足要求,j值只能增大,减少就不符合定义。

至此,我们证明了把j回溯到大于m的任何位置都会得到错误的结论,且验证了移动到m可以得到正确的结论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: