Loading

exkmp(Z函数)

exkmp(Z函数)

题意

给定两个字符串 A B,要求出两个数组:

  • BB 的每一个后缀的 LCP 长度 (next)
  • BA 的每一个后缀的 LCP 长度 (extend)

\(\operatorname{xor}_{i=0}^{n-1} i \times (nxt_i + 1)\) 以及 \(\operatorname{xor}_{i=0}^{n-1} i \times (ext_i + 1)\)

算法

图中 S 表示 AT 表示 B

nxt[]next[]ext[]extend

现在已求得 nxt[1~n] 以及 ext[1~i-1],要求 ext[i]

设置变量 app 代表以 a 为起始位置的字符匹配成功的最右边界

那么我们可以得到:A[a~p]=B[0~p-a]

现在 A[i] 对应 B[i-a]

i+nxt[i-a]<p,如上,那么此时 ext[i]=nxt[i-a]

i+nxt[i-a]=p,如上,那么此时我们可以从 A[p]B[p-a] 往后匹配

i+nxt[i-a]>p,如上,那么此时我们可以让 ext[i]=p-i

时间复杂度\(O(|A|+|B|)\)

code

#include <bits/stdc++.h>
using namespace std;

const int N=2e7+5;

int nxt[N],ext[N];

inline void get_next(char *B,int m){
    int a=0,p=0;
    nxt[0]=m;
    for(int i=1;i<m;++i){
        if(i>=p||i+nxt[i-a]>=p){
            if(i>=p)
                p=i;
            while(p<m&&B[p]==B[p-i])
                ++p;
            nxt[i]=p-i;
            a=i;
        }
        else
            nxt[i]=nxt[i-a];
    }
}

inline void get_extend(char *A,char *B,int n,int m){
    int a=0,p=0;
    for(int i=0;i<n;++i){
        if(i>=p||i+nxt[i-a]>=p){
            if(i>=p)
                p=i;
            while(p<n&&A[p]==B[p-i])
                ++p;
            ext[i]=p-i;
            a=i;
        }
        else
            ext[i]=nxt[i-a];
    }
}


int n,m;
char A[N],B[N];

inline void Z(){
    get_next(B,m);
    get_extend(A,B,n,m);
}

signed main(){
    scanf("%s%s",A,B);
    n=strlen(A),m=strlen(B);
    Z();
    long long a=0;
    for(int i=0;i<m;++i) a^=1ll*(i+1)*(nxt[i]+1);
    cout<<a<<endl;
    a=0;
    for(int i=0;i<n;++i) a^=1ll*(i+1)*(ext[i]+1);
    cout<<a<<endl;
}
posted @ 2022-07-02 12:31  Into_qwq  阅读(46)  评论(0编辑  收藏  举报