• 字符串笔记


    后缀系列

    后缀自动机

    1、parent_tree

    对于某一个子串,在某一些位置(为结尾)出现过,出现过的所有位置集合叫做endpos。

    parent_tree是这样一棵树:一个节点代表一个endpos集合,节点上的字符串的endpos全部相等且恰为该节点代表的endpos集合;

    每一个节点的endpos集合都是父亲节点的子集。

    可以发现一个性质:设每一个点上的子串的最长串长为maxlen,最短为minlen,则父亲的maxlen+1必然等于儿子的minlen,而且minlen~maxlen必然每一个len都对应一个子串。

    可以证明parent_tree的节点个数为O(n)。

    后缀自动机的节点就是parent_tree的节点。

    2、后缀自动机

    自动机本身是个DAG。

    通过DAG上从初始点出发的每一条路径,都能组成一个子串,且所有子串都能被表示出来。

    维护下列东西:

    fa:parent_tree上的fa。

    len:每个节点的maxlen(如上所阐述)(minlen可以通过fa的maxlen来得到)

    ch:儿子。DAG上的边指向的点。一个点的ch数量就是字符集,每一个ch代表了:在上一个点的子串后接上一个字符获得的子串所属的点。

    每次加入一个字符c,创立一个新节点:

    首先,对于上一次加入的字符的初始点,若它和它的祖先们(parent_tree上的)都没有儿子c,那就把儿子c连向自己。

    然后找到第一个已经有了儿子c的点x。

    考虑这个点的儿子c,称为ch[x][c]:如果这个len[x]+1=ch[x][c],说明ch[x][c]里面存的东西正好是符合parent_tree定义的,把新节点的fa连向它;

    否则,将x点拆成两个点u、v:len[u]+1=ch[x][c],len[v]=len[x];然后,v和新节点的fa都是u。u的fa就是x的fa。把连向x的ch中长度满足条件的连向u,长度不满足条件的连向v。u和v的ch和x是一样的。

    这样就维护好了,可以证明边数也是O(n)的。

    3、经典操作

    parent_tree从下到上更新:

    按照maxlen来对节点基数排序。

    求两个串的最长公共子串:

    在自动机上面跑(往下走ch、往上跳fa)就好了。注意nowlen的更新。

    4、例题:

    XSY3930 最长公共子串对

  • 相关阅读:
    好玩的SQL
    Oracle常用函数
    树控件DeleteAllItems之前先SelectItem(NULL)
    MFC控件位置调整
    C++中一个0xC0000005访问冲突问题
    为MFC按钮添加各种图片
    LVN_ITEMCHANGED(OnItemchanged)通知响应多次的问题
    android 里边的mk文件的解析
    定义属于自己的标题栏
    block 影响代码执行由上往下执行顺序 从而影响功能的解决
  • 原文地址:https://www.cnblogs.com/youddjxd/p/14545986.html
Copyright © 2020-2023  润新知