zoukankan      html  css  js  c++  java
  • 字符串笔记

    后缀系列

    后缀自动机

    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 最长公共子串对

  • 相关阅读:
    在Ubuntu_meta 16.04中设置默认Python3.5的命令
    树莓派安装中文输入法Fcitx及Google拼音输入法
    树莓派安装ubuntu_meta并配置开发环境
    业务代表模式
    MVC 模式
    访问者模式
    模板模式
    Linux进程调度与抢占
    IP地址
    策略模式
  • 原文地址:https://www.cnblogs.com/youddjxd/p/14545986.html
Copyright © 2011-2022 走看看