首页 > 其他分享 >2023-03-17- 后缀自动机

2023-03-17- 后缀自动机

时间:2023-07-05 12:13:51浏览次数:34  
标签:03 17 SAM 状态 delta 2023 字符串 mathtt mathrm

我直接忽略掉这个玩意的原理。

或许我应该从自动机开始,更确切地说我应该从 确定有限状态自动机 (\(DFA\)) 开始。

\(\mathbb{DFA}\)

\(\mathtt{Definition}\)

首先给出一些前置的定义。

  • \(Q\),有限状态集合。
  • \(\Sigma\),有限字符集。
  • \(\delta\),转移函数, \(Q \times E \rightarrow Q\)。
  • \(q_0\),起始状态。
  • \(F \subset Q\),接受状态集合。

设 \(N = (Q, \Sigma, \delta, q_0, F)\) ,定义 \(E(q)\) 表示从 状态 \(q\) 出发,只沿着 \(\epsilon\) 转移能够到达的集合。
然后构造 \(M = (Q', \Sigma, \delta', E(q_0), F')\),其中

  • \(Q'\),状态集合, \(Q' = \mathcal{P}(Q)\)
  • \(\delta'\),转移函数,\(Q' \times E \rightarrow Q',\delta'(S, c) = \bigcup q \in S, q' \in \delta(q, c) E(q')\)
  • \(F'\),终止状态集合,\(F' = \{ S \subset Q \mid S \cap F \not = \empty \}\)。

工作时自动机会一个一个读入字符集,按照 \(\delta\) 转移,如果在转移结束之后处于一个接受状态,那么成这个自动机接受这个字符串,反之称这个自动机不接受这个状态。

当一个状态 \(S\) 没有字符 \(c\) 的转移时,令 \(\delta(S, c) = \mathrm{null}\) ,\(\mathrm{null}\) 不属于任何接受状态,也无法进行转移。

于是我们可以简单地定义自动机了。

\(\mathbb{SAM}\)

\(\mathtt{Definition}\)

一个字符串的 后缀自动机(\(\mathrm{SAM}\)) 就是一个 接受且仅接受 这个字符串的 所有后缀\(DFA\)

那么根据定义,如果一个字符串 \(t\) 是 \(s\) 的后缀,当且仅当 \(\mathrm{SAM}_{s}(t) = \mathtt{true}\) ,同样可以知道,如果一个字符串 \(t\) 是 \(s\) 的子串,当且仅当 \(\delta_s(t) \not= \mathrm{null}\) ,很好理解,因为如果在 \(t\) 的后面增加一些字符成为 \(t'\),\(t'\) 一定是 \(s\) 的后缀。

\(\mathtt{Construction}\)

考虑一下,还是先写构造的方式。

\(\Theta(n^2) \ \mathrm{SAM}\)

首先看一个很简单的 \(\mathrm{SAM}\) ,即是说建一棵字典树,直接把所有后缀塞进去,每次标记终止节点为接受状态,就可以得到一个状态数 \(\Theta(n^2)\) 的 \(\mathrm{SAM}\) 。

\(\Theta(n) \ \mathrm{SAM}\)

然后应用关于自动机的一些科技,对这个玩意进行 任意 \(DFA\) 压缩
首先写对 \(\Theta(n^2) \ \mathrm{SAM}\) 的压缩,最后写个泛化的压缩方式。

下面定义一些变量。

\(\mathtt{right \ \& \ reg}\)

注意到这个是个集合,对于一个字符串 \(t\) ,如果它在 \(s\) 中出现的位置的集合为 \(\{ [l_1, r_1), [l_2, r_2), \dots [l_n, r_n)\}\) ,那么 \(\mathtt{right}(t) = \{ r_1, r_2, \dots, r_n \}\) 。

定义 \(\mathtt{right}\) 集合的等价类为所有 \(\mathtt{right}\) 集合相等的字符串, \(\mathtt{reg}(v)\) 表示从状态 \(v\) 开始能识别的字符串的集合,就是说 \(t \in \mathtt{reg}(v) \Leftrightarrow \delta (v, t) \in F\) 。

这时我们给 字符串 \(t\) 后面接上一个字符串 \(s[r_i, n], r_i \in \mathtt{right}(t)\) 变成 \(t'\) 使得 \(t'\) 成为 \(s\) 的后缀,所以如果 \(\mathtt{right}(t_1) = \mathtt{right}(t_2)\) ,那么 \(\mathtt{reg}\mathrm{(SAM)}(t_1) = \mathtt{reg}\mathrm{(SAM)}(t_2) = s[r_i, n], r_i \in \mathtt{right(t_1)}\)。

这样的 \(\mathrm{SAM}\) 的状态数是最少的当且仅当 \(\mathtt{reg}\) 集合对应的状态两两不同。

\(\mathtt{minl \ \& \ maxl}\)

表示 这个状态下对应的最长的字符串和最短的字符串
根据定义可以知道 \(v\) 对应的任意一个字符串都是 \(\mathtt{maxl}(v)\) 的后缀,且不是 \(\mathtt{minl}(v)\) 的真后缀。并且,\(v\) 包含了所有这样的字符串。

\(\mathtt{parent}\)

后面简写为 \(\mathtt{par}\) 。
对于每个状态 \(v\) ,\(\mathtt{minl}(v)[1, n - 1]\) 对应的状态。
根据定义可知 \(\mathtt{len}(\mathtt{minl}(v)) = \mathtt{len}(\mathtt{maxl}(v)) + 1\) ,并且可以发现由指向 \(\mathtt{par}\) 的边可以构成一棵树,称为 \(\mathtt{par}\) 树。
此时 \(\mathrm{SAM}\) 上的接受状态就是包含 \(r_i = n\) 的一些 \(\mathtt{right}\) 集合的等价类,那么反过来我们可以通过 \(\mathtt{par}\) 树确定 \(\mathrm{SAM}\) 上面可接收状态的集合。

\(\mathtt{Code}\)

struct SuffixAutomaton {
  int siz, last;
  LL tot;
  struct Node { int len, par; map<char, int> nxt; } s[MAXN << 1];
  void init() { s[0].len = 0, s[0].par = -1, siz = 1, last = 0; }
  void extend(char c) {
    int cur = ++siz;
    s[cur].len = s[last].len + 1;
    int p = last;
    while (p != -1 && !s[p].nxt.count(c)) {
      s[p].nxt[c] = cur;
      p = s[p].par;
    }
    if (p == -1) {
      s[cur].par = 1;
    } else {
      int q = s[p].nxt[c];
      if (s[p].len + 1 == s[q].len) {
        s[cur].par = q;
      } else {
        int clone = ++siz;
        s[clone].len = s[p].len + 1;
        s[clone].nxt = s[q].nxt;
        s[clone].par = s[q].par;
        while (p != -1 && s[p].nxt[c] == q) {
          s[p].nxt[c] = clone;
          p = s[p].par;
        }
        s[q].par = s[cur].par = clone;
      }
    }
    last = cur;
    tot += s[cur].len - s[s[cur].link].len;
  }
} sam;

\(\mathtt{DFA \ minimization}\)

标签:03,17,SAM,状态,delta,2023,字符串,mathtt,mathrm
From: https://www.cnblogs.com/Iridescent41/p/17528174.html

相关文章

  • 2023-03-05-NOI 春测 游记
    终究是我的锅。/ll想了很久,不知道怎么写。最近遇到很多令人困惑的事,我现在也不是很能理解我在那一天早上发生了什么?总之我心情很不好就是了。考试之前发生了什么都忘了,因为早上起来头有点晕。下面是整个考试的经历。before没进考场时心态还是比较稳健,但是当我真正坐下来......
  • 2023-03-05-CQOI 2023 省选 游记
    心高气盛难免对自己抱有幻想。Before2023-04-01上接2023春测。以及停课时模拟赛复习。2023-04-01来得比较早,听游老师强调了一些低级错误,然后吴老师过来给我们打气。心理稍微稳了一点,合了影就去考场了。中途发生了一个小插曲,我以为桌子上写的是座位号,于是坐在了......
  • 2023-02- NOI 春测复习记录
    Tosaygoodbyeistodiealittle.由于不可抗拒力,复习计划咕咕咕了。也不一定呢?P4755link关键在于要发现暴力的复杂度是对的。好像这个方法叫做\(\max\)分治,首先可以建一个大根的笛卡尔树,然后只需要对该点的管辖区间进行计算就可以了。具体做法是直接以最大值的点\(......
  • 2023-01-26-Poly Template
    尝试强行记忆,尝试失败。。。把最终所有的式子写一遍。约定\(F^{*}(x)\)表示\(\pmod{x^{n/2}}\)意义下的结果,\(F^{R}(x)\)表示系数翻转。\(\mathtt{Summary}\)\(\mathtt{Poly\INV}\)\[G(0)=F(0)'\\G(x)=G^{*}(x)(2-F(x)G^{*}(x))\]\(\mathtt{Poly\Sqrt}\)\[......
  • 成语积累 20230705
    焚膏继晷:焚:点燃;膏:灯油或蜡烛;继:接续;晷:日影或日光。意思是点燃灯烛来接替日光照明。形容夜以继日的用功读书或努力工作。例句:~,兀兀穷年。鹤唳华亭:表示思念,怀旧之意。亦为慨叹仕途险恶,人生无常之词。例句:但~,贵何似贱;珠沉金谷,富不如贫。拾人牙慧:牙慧:牙齿内剔出的余食。比喻拾取别人......
  • Springboot No bean named 'XXXXX' available 问题解决
    一、问题描述近日在工作中遇见了一个bug,后端程序频频报错Nobeannamed'XXXXX'available。对比同类程序文件,没有发现有任何特殊之处。在网上搜索方法基本上就是扫描包配置、注解问题、路径问题等,皆不能解决我的问题。排查问题是发现出现问题的类命名不符合驼峰规范,按照这个......
  • 早期癌症筛查测试行业市场现状及未来发展趋势2023
    2023年全球及中国早期癌症筛查测试行业头部企业市场占有率及排名调研报告本文调研和分析全球早期癌症筛查测试发展现状及未来趋势,核心内容如下:(1)全球市场早期癌症筛查测试总体规模,按收入进行了统计分析,历史数据2018-2022年,预测数据2023至2029年。(2)全球市场竞争格局,全球市场头部企......
  • 17需求工程概述
    软件需求指用户在系统功能、行为、设计约束、性能等的期望需求工程主要活动划分为5个阶段需求获取需求分析形成需求规格需求确认与验证形成需求基线,就是经过评审的需求规格需求管理:变更控制、允许变更后就是版本控制,接着式需求跟踪,最后是需求状态跟踪需求管理是对需求基线......
  • 2023-07-05 Matlab中的数值积分.md
    2023-07-05Matlab中的数值积分Matlab数值积分在《计算方法》一书中有介绍基本的数值分析中的积分方法,我们这里重点关注Matlab是如何帮助我们快速计算数值积分。1.integral簇函数integral簇函数下包含integral,integral2,integral3三个函数,分别对应于一重积分,二重积分和......
  • 【2023-07-02】连岳摘抄
    23:59其实,偶然并不存在,你必须得到某个东西时,它的出现绝非偶然,而是你自己,你自己的渴望和需求将你引向那里。                                                 ——黑塞......