luoguP5410 【模板】扩展 KMP(Z 函数)

新学一发扩展 KMP.   

和 KMP 一样,都是均摊复杂度 $O(n)$.  

code:   

#include <bits/stdc++.h>        
#define N 20000007    
#define ll long long  
#define setI(s) freopen(s".in","r",stdin) 
#define setO(s) freopen(s".out","w",stdout) 
using namespace std;    
int z[N],p[N];                
char a[N],b[N];        
void Z(char *s,int len) 
{
    for(int i=1;i<=len;++i) z[i]=0;    
    z[1]=len;    
    for(int i=2,l=0,r=0;i<=len;++i) 
    {
        if(i<=r) z[i]=min(z[i-l+1],r-i+1);    
        for(;i+z[i]<=len&&s[i+z[i]]==s[z[i]+1];++z[i]);   
        if(i+z[i]-1>r) l=i,r=i+z[i]-1;     
    }
}     
void exkmp(char *s,int n,char *t,int m) 
{
    Z(t,m);      
    for(int i=1;i<=n;++i) p[i]=0;    
    for(int i=1,l=0,r=0;i<=n;++i) 
    {
        if(i<=r) p[i]=min(z[i-l+1],r-i+1);      
        for(;i+p[i]<=n&&s[i+p[i]]==t[p[i]+1];++p[i]);           
        if(i+p[i]-1>r) l=i,r=i+p[i]-1;   
    }
}
int main() 
{ 
    // setI("input");           
    int n,m; 
    scanf("%s",a+1),n=strlen(a+1);   
    scanf("%s",b+1),m=strlen(b+1);              
    exkmp(a,n,b,m);    
    ll ans=0;   
    for(int i=1;i<=m;++i) ans^=1ll*i*(z[i]+1);    
    printf("%lld\n",ans);   
    ans=0;    
    for(int i=1;i<=n;++i) ans^=1ll*i*(p[i]+1);    
    printf("%lld\n",ans);   
    return 0;  
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/12564433.html