zoukankan      html  css  js  c++  java
  • 后缀自动机(学习笔记)

    要看懂本文可能至少需要知道什么是后缀(

    还得知道一些自动机的概念(

    和ac自动机有个很大的不同,sam它的字符是放在边上的(似乎放在点上也可以),因为大部分图都是这样的,(比如下图),把点看成了能接受从起点到该点的路径串的状态。

    T状态能接受abc和bc字符串。  ( ps:图随手画的)

    首先定义一些概念:

    endpos(t):表示子串t的结束位置。比如aabaa,endpos(“aa”)={2,5}

    在sam中,每个endpos(t)即为一个状态,也就是说几个endpos(t)相同的不同子串共用一个状态;显然abab中,ab和b是共用一个状态的。

    先定义一个状态:x

    string(x):表示x状态能接受的所有字符串。

    可得性质1

    在string(x)中,短串是长串的后缀。

    再定义几个东西:

    string(x)_max,string(x)_min:分别其中的最长串、最短串。

    又得性质2:

    string(x)=={string(x)_min,string(x)_min+1,string(x)_min+2,,,,,,string(x)_max},就是说最长串的后缀连续出现在string(x)中,直到string(x)_min。

    那么又会有疑问了,那长度小于string(x)_min的后缀呢?由于那些后缀的endpos(t)多了几个元素,便不和它们共用一个状态了。但还是有个东西把那些后缀也表示了出来。

    定义Suffix指针:指向属于它后缀的状态。如下图绿色的线:

    至此,,,似乎已经明白后缀自动机的结构了。

    再补充两个点:

    所有的子串即为从S出发的所有路径,即为所有状态的string(x)之和。

    能轻易地知道每个子串的所有后缀。

    状态总数为O(n)。

    如何O(n)构造呢?

    考虑递推,已经建好了前n-1个字符,再加入一个字符c,无非又多了n个子串。

    定义pre[n-1]为前面n-1个字符构成的字符串。

    这个时候我们只需看当时的末状态,即能接受pre[n-1]的那个状态,因为pre[n-1]的所有后缀加一个字符c就是新增的n-1个子串。

    前面说过string(x)_max,string(x)_min,就不多说了,用一条边为c的边连接末状态和新状态,就解决了max-min+1个子串,也解决了pre[n]。

    剩下可以分3类情况:

    这个时候就需要借用末状态的Suffix指针了。

    定义Suffix指针指向了y状态,上面说的新增状态为z。

    1,y状态+c,在原有sam上不能发生转移,y新增一条边c指向z。

    2,y状态+c,算了,太tm难了。

  • 相关阅读:
    Leetcode929.Unique Email Addresses独特的电子邮件地址
    Leetcode914.X of a Kind in a Deck of Cards卡牌分组
    new Date()设置日期在IOS的兼容问题
    koa2 使用passport权限认证中间件
    当 better-scroll 遇见 Vue
    百度地图开发
    通过Ajax方式上传文件,使用FormData进行Ajax请求
    app中页面滑动,防止a链接误触
    js判断是微信、QQ内置浏览器打开页面
    百度天气预报接口介绍
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/9801069.html
Copyright © 2011-2022 走看看