zoukankan      html  css  js  c++  java
  • 扩展KMP(Z函数)

    用途

    (O(n))求一个串与另一个串的每一个后缀的LCP长度

    算法过程

    其实个人感觉跟KMP关系不大,反倒与Manacher有异曲同工之妙

    求解Z函数

    定义

    s(i,j):字符串(S)的第(i)为到第(j)

    suf(i):以 (i) 开头的后缀,即(s(i,n)​)

    z[i]:s(1,n)与(suf(i))的LCP长度,(z[1]=n)

    r:当前匹配过的最靠右的点

    考虑已知(z[1]sim z[i-1]),求出(z[i])

    第一种情况

    (i>r),直接从(0)开始暴力匹配

    第二种情况

    当前(s(l,r))对应匹配(s(1,r-l+1)),如图中蓝色部分所示

    (i)对应的位置是(i-l+1),如果(z[i-l+1])不超过(r-i+1),那么(z[i-l+1])一定是合法的,直接赋值

    第三种情况

    (i)对应的位置是(i-l+1),如果(z[i-l+1])超过(r-i+1),那么(r-i+1)以内的一定是合法的,剩下的需要暴力判一判

    代码

    inline void getz(char *s,int n){
    	memset(z+1,0,n<<2);
        z[1]=n;len=n;
    	for(int i=2,l=0,r=0;i<=n;++i){
    		if(i<=r)z[i]=min(z[i-l+1],r-i+1);
    		while(i+z[i]<=n&&s[i+z[i]]==s[z[i]+1])++z[i];
    		if(i+z[i]-1>r)l=i,r=i+z[i]-1;
    	}
    }
    

    求一个串与另一个串的每一个后缀的LCP长度

    与求Z函数类似

    inline void calc(char *s,char *a,int n,int *ans){
    	memset(ans+1,0,n<<2);
    	for(int i=1,l=0,r=0;i<=n;++i){
    		if(i<=r)ans[i]=min(z[i-l+1],r-i+1);
    		while(i+ans[i]<=n&&ans[i]+1<=len&&a[i+ans[i]]==s[ans[i]+1])++ans[i];
    		if(i+ans[i]-1>r)l=i,r=i+ans[i]-1;
    	}
    }
    

    例题

    CF1313E Concatenation with intersection

    (f_i)表示(a[i])(s)的LCP长度,(g_i)表示(b[i])(s)的LCS长度,这两个可以(O(n))使用exKMP求

    转化题意为满足以下四个条件的(f_i+g_j-m+1)之和

    • (ile j)
    • (i+m-1>j)
    • (f_i>0,g_j>0)
    • (f_i+g_jge m)

    对第二个限制容斥一下,先不考虑第二个限制,减去(jge i+m-1)的贡献

    考虑维护(g_jge max(1,m-f_i))(f_i+g_j-m+1)之和

    (f_i)(g_j)拆开,两个树状数组(T1,T2),分别维护(g_jge max(1,m-f_i))(g_j)之和的(j)的个数,满足(g_jge max(1,m-f_i))(g_j)之和

    贡献为((f_i-m+1) imes T1+T2​)

    注意到(a/b)不能把(s)占满,求出的(LCP/LSP)要与(m-1)(min)

  • 相关阅读:
    APP开发关于缓存
    SlidingMenu+Fragment实现当前最流行的侧滑
    深入理解dp px density
    HDU1847--Good Luck in CET-4 Everybody!(SG函数)
    【转】博弈论——acm
    HDU1846--Brave Game(巴什博弈)
    HDU2179--pi(麦金公式)
    HDU1026--Ignatius and the Princess I(BFS记录路径)
    HDU1237--简单计算器(栈的应用)
    HDU3398—String-(组合数)
  • 原文地址:https://www.cnblogs.com/harryzhr/p/14682907.html
Copyright © 2011-2022 走看看