• 退役前的字符串学习


    exkmp:

    线性求出字符串的任何一个后缀与自身的lcp长度

    设其为(z)数组,(z[i])表示([1,n])([i,n])lcp的长度

    考虑从前往后依次求出(z[i])

    考虑维护(i+z[i]-1)最大的(j)

    那么如果(i<=j+z[j]-1),考虑([i,j+z[j]-1]=[i-j+1,z[j]-1])

    (z[i])就从(min(z[i-j+1],j+z[j]-i))继承过来即可

    然后剩下的部分暴力往后匹配

    注意你如果需要暴力往后匹配,(j+z[j]-1)必然会被当前的(i+z[i]-1)更新,每匹配一位就至少变大(1)

    因为如果(min(z[i-j+1],j+z[j]-i)=z[i-j+1])(z[i])是不会更新的,因为两者一样的部分长于(z[i-j+1])(z[i])不会比(z[i-j+1])

    综上所述,复杂度是(O(n))

    一份含exkmp的代码code



    lyndon words and runs

    没有lemma的证明(有些没看懂)

    lyndon串:一个满足除了本身以外的后缀,字典序都比它本身大的串

    一个性质:两个lyndon串(s,t),若(s)严格小于(t),则(st)是lyndon串

    一个串的lyndon分解:把一个串分解成(s_1,s_2...s_k),满足(s_1,s_2...s_k)都是lyndon串,且(s_1 geq s_2 geq ... geq s_k),这里(geq)表示字典序不小于

    一个性质:一个串的lyndon分解存在且唯一

    求lyndon分解:Duval's Algorithm

    增量法构造lyndon分解

    考虑我们当前已经有([i,|S|])的lyndon分解,要求出([i-1,|S|])的lyndon分解

    考虑维护一个栈,栈中每个元素是一个lyndon串的结尾

    栈中元素需要满足这些lyndon串不降

    向栈中加入(i-1)

    若当前(s[i:st[top]] > s[st[top]+1:st[top-1]])

    则这两个可以合并,弹出栈顶

    runs:定义三元组((i,j,p))是一个run,当且仅当(s_{j+1} eq s_{j-p+1},s_{i-1} eq s_{i+p-1})(p)([i,j])最小的出现至少两次的循环节。

    求runs

    求出以每个位置为左端点的最长lyndon子串

    这个其实就是上面的算法里每一步添加以后的栈顶元素

    runs的求解:

    对于上面的每一个串([l,r]),以它的长度为周期,向左/右扩展到(l',r'),若([l',r'])的长度不小于([l,r])长度的两倍,则([l',r'])是一个runs

    求解的时候要把字符大小关系反过来再求一次lyndon word和runs,才能求出全部的

    模板题code

  • 相关阅读:
    JVM收藏的文章
    【转】Mysql相关子查询&&MySQL获取分组后的TOP N记录
    【转】JVM--内存区域划分
    【转】Nginx location写法
    【转】Dockerfile
    CORS web.xml 里配置
    分布式事务
    maven+dubbo+SpringMVC 项目搭建
    dubbo 报错
    多重背包问题:POJ2392
  • 原文地址:https://www.cnblogs.com/deaf/p/14855671.html
Copyright © 2020-2023  润新知