exkmp(Z函数)
exkmp(Z函数)
题意:
给定两个字符串 A B,要求出两个数组:
B与B的每一个后缀的LCP长度 (next)B与A的每一个后缀的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 表示 A,T 表示 B
nxt[] 即 next[],ext[] 即 extend
现在已求得 nxt[1~n] 以及 ext[1~i-1],要求 ext[i]
设置变量 a 、p,p 代表以 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;
}

浙公网安备 33010602011771号