首页 > 其他分享 >普及 SAM

普及 SAM

时间:2024-11-08 08:48:50浏览次数:1  
标签:子串 nxt 普及 SAM 后缀 结点 DAWG

参考了一些博客,如有侵权,请告知。

内部资料,包不外传。

定义

后缀自动机(SAM)的结构包含两部分,有向无环单词图(DAWG)和 parent 树。SAM 中的每个节点都同时存在于这两个结构中。

以下假设我们是关于字符串 \(s\) 的 SAM。

DAWG

DAWG 是一个 DAG。

我们令起始结点为 \(st\),\(st\) 在 DAWG 中表示一个空串,而其他所有结点均 \(s\) 的一个或多个子串。

对于 DAWG 中的每条有向边都有一个字符 \(c\),一个结点 \(x\) 所包含的子串为从 \(st\) 走到 \(x\) 路径上的字符依次拼接得到的结果,因为有多条路径,所以结点 \(x\) 可能包含很多子串。

为了描述方便,如果结点 \(x\) 包含 \(s\) 的一个后缀,那么我们称这个点为关键点。

结点

  • 每一个结点代表的所有子串,一定是 \(s\) 某个前缀中若干长度只相差 \(1\) 的后缀。
  • 结点 \(x\) 代表的所有子串中,最长子串长度记为 \(\max ( x )\),最短子串长度记为 \(\min ( x )\)。
  • 我们记 endpos 为一个子串在 \(s\) 中所有出现过的结尾位置集合,则一个结点所有子串的 endpos 相同。
  • 任意两个结点的 endpos 不同,否则即可将其合并为一个结点。

有向边

\(u \to v\) 有连边则表示 \(u\) 的所有子串加上这条边所代表的字符 \(c\) 后能够变成的子串被 \(v\) 包含,但不一定其是 \(v\) 的所有子串(\(v\) 可能由多个点连边转移过来)。

后缀链接与 parent tree

注意:后缀链接并没有和 DAWG 中的有向边有直接联系。

  • 记 \(u\) 的后缀链接所指的结点为 \(nxt_u\),如果 \(nxt_u = v\),当且仅当 \(\min(u) = \max (v) + 1\),且 \(nxt_u\) 的子串是 \(u\) 的子串的后缀。
  • 对于 \(u\) 和 \(nxt_u\) 来说,\(nxt_u\) 的 endpos 集合包含 \(u\) 的 endpos 集合。
  • 后缀链接本质构成了一棵以 \(st\) 为根的内向树,我们称这棵树为 parent tree。

构造

大家可以通过构造感受 SAM 的有向边和后缀链接所表示的深层含义。

正常情况下,构造 SAM 的复杂度是 \(O(nV)\) 的,\(V\) 为字符集大小。

SAM 的构造是一个在线的增量算法,也就是说我们通过 \(s\) 的 SAM 得出 \(s + c\) 的 SAM。一般情况下我们选择直接记代码,当然你也可以通过下述例子感受 SAM 的构造过程与严谨逻辑。

首先,当 \(s\) 为 acbabc 时,我们的后缀自动机应该长这样(比较复杂,其实是为了让读者更清楚的理解 SAM 的结构,注意看清楚箭头方向):

解释一下其中的东西:

  • 虚线表示有向边,实边表示后缀链接,\(u \to nxt_u\) 有一条有向的实边(后缀链接)。
  • \(v_1\) 为 \(st\) 结点,也就是起始结点,其中 \(v_2, v_3, v_4, v_5, v_6, v_7\) 代表子串之一是 \(s\) 的一个后缀,其中 \(v_7\) 为 \(s\) 串,然后从 \(v_6\) 到 \(v_2\) 长度递减,这些点也就是我们上面说过的关键点。
  • 为了方便,我们将把 \(v_2, v_3, ..., v_9\) 这些结点所代表的字符串表示出来,如果你不记得表示哪些字符串了,可以看一眼。
    • \(v_2\):

标签:子串,nxt,普及,SAM,后缀,结点,DAWG
From: https://www.cnblogs.com/alexande/p/18533912

相关文章

  • langchain agent with tools sample code
    importasynciofromlangchain_openaiimportChatOpenAIfromlangchain.agentsimporttoolfromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholderfromlangchain.agents.format_scratchpad.openai_toolsimport(format_to_openai_tool_me......
  • 题解:P11253 [GDKOI2023 普及组] 小学生数学题
    所求的式子带除法,模意义下除法计算复杂度带\(\log\)太慢了,先改写成乘法:\(\sum_{i=1}^ni!\timesi^{-k}\)。想求这个式子,最简单的思路就是对于每个整数\(i\in[1,n]\),分别预处理出\(i!\)和\(i^{-k}\)的值,最后乘起来再\(O(n)\)暴力加起来就好了!对于\(i!\),注意到:\[i!=\b......
  • 从Samza到Flink:Java实现数据流转换
    标题:从Samza到Flink:Java实现数据流转换摘要:本文将介绍如何使用Java语言实现将数据流从Samza转换为Flink的过程。通过使用Flink的丰富功能和优化技术,我们可以轻松处理大规模数据流,并实现精确和高效的数据处理。引言Samza和Flink是两个非常流行的分布式数据处理框架,它们都......
  • 150道MySQL高频面试题,学完吊打面试官--InnoDB索引与MyISAM索引实现的区别+一个表中如
    前言本专栏为150道MySQL大厂高频面试题讲解分析,这些面试题都是通过MySQL8.0官方文档和阿里巴巴官方手册还有一些大厂面试官提供的资料。MySQL应用广泛,在多个开发语言中都处于重要地位,所以最好都要掌握MySQL的精华面试题,这也是面试官最喜欢问的,现在面试官在面试的时候更关......
  • 征程 6E camera diag sample
    01功能概述本文的demosample主要描述当前camera相关外设诊断的当前状态,并提供自定义实现的方法及使用说明。1.1软件架构说明本sample基于现已实现的camera诊断架构,libcam内的外设诊断功能对外设硬件状态进行监测,并支持将故障状态发送给MCU处理,或通过事件回调方式......
  • P1088 [NOIP2004 普及组] 火星人
    [NOIP2004普及组]火星人题目描述人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学家,科学家破解这个数字的含义后,再把一个很小......
  • 打卡信奥刷题(159)用C++工具信奥P1416[普及组/提高] 攻击火星
    攻击火星题目描述一群外星人将要攻击火星。火星的地图是一个nnn个点的无向图。这伙外星人将按照如下方法入侵,先攻击度为0......
  • 打卡信奥刷题(161)用C++信奥P1451[普及组/提高] 求细胞数量
    求细胞数量题目描述一矩形阵列由数字000到999组成,数字......
  • Samba
    StorageSrvSAMBA​ 创建samba共享,本地目录为/data/share1,要求:​ 共享名为share1;​ 仅允许zsuser用户能上传文件;​ 创建samba共享,本地目录为/data/public,要求:​ 共享名为public。​ 允许匿名访问。​ 所有用户都能上传文件。配置1.安装服务yuminstall-ysamb......
  • 题解 洛谷 Luogu P1308 [NOIP2011 普及组] 统计单词数 C++
    题目传送门:P1308[NOIP2011普及组]统计单词数-洛谷|计算机科学教育新生态https://www.luogu.com.cn/problem/P1308getline() 会清除使当次getline() 终止的换行,而cin 不会因此cin 以换行终止,之后还需要getline()的话,需要用getchar() 吞换行Linux的一些相......