学习KMP的时候有点感想,记录一下。
KMP的主要优势在于主串不回溯,子串根据一定规则回溯,因此可以达到O(n+m)的时间复杂度,这个规则就是next数组。
当主串和子串以0为起始位置时,next数组的规律如下:
1) next[j] = -1,j = 0
2) next[j] = max(k)|0<k<j,P[0...k-1]=P[j-k,j-1]
3) next[j] = 0 ,其他
当主串和子串以1为起始位置的时候next数组的数值加一。
当对主串(ori,用i指向当前位置)进行匹配的时候,子串(par,用j指向当前位置)回溯的值为next[j],即有:
<pre name="code" class="cpp"><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="cpp"><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="cpp">if(j==-1||ori[i]==par[j])
{
++i;
++j;
}
else
{
j=next[j]
}
其中
j==-1
的判断是指:子串回溯到头也找不到可匹配项,因此下一次用主串的下一个值与子串第一个值进行匹配。如果当前值能够匹配上,则继续匹配下一个。
当求next数组中的值的时候,其实就是将子串的前缀和后缀分别当做原匹配中的主串和子串进行匹配的过程,只是要边匹配,边对next数组进行修改:
<pre name="code" class="cpp">if(j==-1||ori[i]==par[j])
{
++i;
++j;
next[i]=j;
}
else
{
j=next[j]
}
当前值若匹配成功,则匹配下一个,同时记录在next中,注意理解上文标红部分的k-1和j-1。
只要理解next的这个特性,整个KMP算法就很好理解了。