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]]\)

分情况讨论:

  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]\)
  2. 否则,\(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;
}
posted @ 2025-06-22 12:11  XP3301_Pipi  阅读(10)  评论(0)    收藏  举报
Title