ExKMP / Algorithm Z
ExKMP / Algorithm Z
1. 问题
现有文本串 \(A\) 与模式串 \(B\)。记 \(|A|=n,|B|=m\)。
令 \(z[i]=LCP(A,A[i,n])\),\(ext[i]=LCP(B[i,m],A)\)。求每个 \(z[i],ext[i]\)。
特别地,\(z[1]=0\)。
2. \(z\) 函数
设当前遍历到 \(A[i]\)。设 \(k\) 是 \(<i\) 的使得 \(k+z[k]-1\) 最大的位置。
若 \(k+z[k]-1<i\),那么暴力求出 \(z[i]\),并更新 \(k\)。
否则,由定义,\(A[k,k+z[k]-1]=A[1,z[k]]\),从而有 \(A[i,k+z[k]-1]=A[i-k+1,z[k]]\),继续得到 \(A[i-k+1,z[i-k+1]-i+k]=A[1,z[i-k+1]]\)。
分情况讨论:
- \(i+z[i-k+1]-1<k+z[k]-1\)。由 \(z[i-k+1]\) 的最大性,\(A[z[i-k+1]+1]\neq A[i-k+2]\)。继续得到 \(A[i-k+2]\neq A[i+z[i-k+1]]\),所以 \(z[i]=z[i-k+1]\)。
- 否则,\(z[i]\) 至少为 \(z[i-k+1]\)。我们先令 \(z[i]=z[i-k+1]\),然后暴力向后匹配,求出最终的 \(z[i]\)。
复杂度 \(O(n)\)。
3. ext 函数
设当前遍历到 \(B[i]\)。设 \(k\) 是 \(<i\) 的使得 \(k+ext[k]-1\) 最大的位置。
类似上面的过程向后做即可。
void ExKMP(){
for(int i=2,k=1;i<=m;i++){
if(k+z[k]-1>=i) z[i]=min(z[i-k+1],k+z[k]-i);
while(i+z[i]<=m&&b[i+z[i]]==b[z[i]+1]) z[i]++;
if(i+z[i]>k+z[k]) k=i;
}
for(int i=1,k=0;i<=n;i++){
if(k+ext[k]-1>=i) ext[i]=min(z[i-k+1],k+ext[k]-i);
while(ext[i]<m&&i+ext[i]<=n&&a[i+ext[i]]==b[ext[i]+1]) ext[i]++;
if(i+ext[i]>k+ext[k]) k=i;
}
z[1]=m;
}

浙公网安备 33010602011771号