基础性质概念

  • 后缀自动机:S的SAM是个DAG,每个节点叫状态,每条带字符ch边表示+ch转移,从开始节点往下,任何一条路径都会对应一个S的子串。

不过为什么要叫"后缀"自动机呢?

  • endpos集合:endpos(s)={s的所有右端点}[s为S的一个子串]
  • 状态(节点):把endpos{}相同的等价类归为一个状态。
  • 边(ch[u][x]):上面定义也说过,状态u中每个s+x集合构成的状态。
  • 推论1:一个等价类中的两个s满足后缀关系。如果不满足,那么存在endpos{}不同。
  • 推论2:由推论1易得等价类中所有s都互相满足前后缀关系而且它们的长度是连续的[l..l+1..r]。假如不连续,存在x,y,z(x是y,z的后缀,y是z的后缀),(endpos简称)ep{x}=ep{z}!=ep{y}所以ep{x}包含ep{y},ep{y}包含ep{z},因此ed{x}=ed{y}=ed{z},与假设矛盾。
  • len[]:表示状态中s最长长度,最短的可以用接下来的变量计算。
  • 推论3:两个等价类的集合要么包含,要么不交,取决与是否有前后缀关系。如果有前后缀关系,len大的那个可以看作len小的那个加一堆前缀很好解释len小包含len大。然后没有后缀关系显然不能有交。

    推论2,3也让我们从后缀角度看待状态。

或许你认为以上就能构成后缀自动机。按照定义来说是的,但是不够。我们还要保证它的状态数和构建操作数为\(O(n)\)

接下来我们会在SAM上连一些虚边,这些虚边会构成有用的fail树

  • par[]:严格包含其ep的最小ep状态点,即par[u]包含的s'是u中s的后缀(而且连续),mnlen[par[u]]=len[u]+1
  • Fail树:father[]为par的一棵树

感性来理解就像某前缀的后缀被分成了很多状态连成一条链。

构建

叫什么增量法,就是在线字符一个一个地加。然后找其最大后缀(par[])。

前提(当前加入第i个,字符为x,这个前缀i的节点为np)

ps.可结合代码理解

首先last为前缀i-1所在的节点。p=last往fail树祖先上跳,同时更新ch[p][x],直到找到一个点ch[p][x]!=0,此时前缀i的最长后缀的长度就是len[p]+1。(因为(在p下面)比len[p]长的后面都没有x)

当然没有这么简单,我们要分三类讨论:

1.没有找到par[],par[np]=rt直接结束

令q=ch[p][x]

2.len[q]=len[p]+1直接par[np]=q

3.len[q]>len[p]+1所代表后缀字符集可以分成两类。长度<=len[p]+1的一类(可以作i前缀(np)的后缀),>len[p]+1的一类跟这次加入无关。

所以容易想到把q拆成两个点,其实拆出1个新点nq(第1类),原来的q(第2类),首先不修改q,用q原来的信息更新nq(par[],ch[][]),len[nq]=len[p]+1,然后更新par[q]=par[p]=nq(Fail树中把q,np连在nq下)。

最后容易遗忘的是p及其上面一些点(因为len[nq]=len[p]+1)原来ch[p][x]=q现在改为ch[p][x]=nq了。

复杂度

可以看看别人的博客

不会证耶?有会证的而且证的很简单的私信我?

code

点击查看代码
struct SAM {
int ch[N][27],t[N],len[N],lst,num,par[N],sz[N];
SAM() {lst=num=1;}
int Insert(int x) {
int p=lst,np=++num;lst=np;len[np]=len[p]+1;sz[np]=1;
for(;!ch[p][x];p=par[p]) ch[p][x]=np;
if(!p) {par[np]=1;return np;}
int q=ch[p][x];
if(len[q]==len[p]+1) {par[np]=q;return np;}
int nq=++num;par[nq]=par[q];len[nq]=len[p]+1;
for(int j=0;j<26;j++)ch[nq][j]=ch[q][j];
par[q]=par[np]=nq;
for(;ch[p][x]==q;p=par[p])ch[p][x]=nq;
return np;
}
}A;

用途(例题)

匹配字符串:

不用说了所有自动机(dfn)都能做的事情

多少个本质不同的字符串(位置不同串相同算同一个)

\(ans= \sum len[u]-len[fa[u]]\)每个(本质不同)字符串都唯一对应与SAM中的节点,而SAM中不同节点表示的字符集没有交集。因此就是每个节点u表示的字符个数(len[par[u]]-len[u])的和。

每个字符串出现了几次

Fail树上,每个节点\(sz[par[u]]+=sz[u]\),每个前缀对应节点(\(sz[np]=1\))

其实sz[u]就是ep等价类u中字符串对应的出现次数了

证明?

把前缀np,sz[np]=1,实际上它会给所有它的后缀+1,然后每个节点对应等价类的ep{r1,r2,r3..rk},显然sz=k。其中每个都会被前缀r1,前缀r2..前缀rk+1各+1。所以刚好+k次,得证。

SAM[详细~bushi]的更多相关文章

  1. sam格式详细说明

    原文链接 https://www.jianshu.com/p/386f520e5de1 The SAM Format Specification(sam格式说明) 1 The SAM Format S ...

  2. [转]后缀自动机(SAM)

    原文地址:http://blog.sina.com.cn/s/blog_8fcd775901019mi4.html 感觉自己看这个终于觉得能看懂了!也能感受到后缀自动机究竟是一种怎样进行的数据结构了. ...

  3. Linux中find、grep命令详细用法

    在linux下面工作,有些命令能够大大提高效率.本文就向大家介绍find.grep命令,他哥俩可以算是必会的linux命令,我几乎每天都要用到他们.本文结构如下: find命令 find命令的一般形式 ...

  4. 初创互联网公司简明创业指南 - YC新掌门Sam Altman

    本文只是一个创业指南的简明版 - 更详细的版本请查看:http://startupclass.samaltman.com 创业之前,你更应该去拥有一个好的创意,而不是一个公司.如果开始前你拥有一个好的 ...

  5. SAMTOOLS使用 SAM BAM文件处理

    [怪毛匠子 整理] samtools学习及使用范例,以及官方文档详解 #第一步:把sam文件转换成bam文件,我们得到map.bam文件 system"samtools view -bS m ...

  6. Luogu P3181 [HAOI2016]找相同字符 广义$SAM$

    题目链接 \(Click\) \(Here\) 设一个串\(s\)在\(A\)中出现\(cnt[s][1]\)次,在\(B\)中出现\(cnt[s][2]\)次,我们要求的就是: \[\sum cnt ...

  7. SAM文件格式

    帮朋友处理sam各式文件,又记不住sam各式每列代表的什么内容,干脆转个帖子留着以后查询. 在SAM输出的结果中每一行都包括十二项通过Tab分隔,从左到右分别是: 1 序列的名字 2 概括出一个合适的 ...

  8. 后缀自动机(SAM)速成手册!

    正好写这个博客和我的某个别的需求重合了...我就来讲一讲SAM啦qwq 后缀自动机,也就是SAM,是一种极其有用的处理字符串的数据结构,可以用于处理几乎任何有关于子串的问题,但以学起来异常困难著称(在 ...

  9. 【H3C交换机】cpu各个进程的详细说明

    display cpu-usage命令用来查看设备CPU占用率的统计信息,以及各个进程的cpu占用率. 各个进程详细说明如下,不同软件版本.盒式和框式的cpu进程略有不同,详细信息可以查看手册中的命令 ...

随机推荐

  1. Codepen 每日精选(2018-3-24)

    按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以打开原始页面. 纯 css 画的抽象小鸟https://codepen.io/gregoryb/f... 纯 css 制作 ...

  2. java的内存泄露是如何发生的,如何避免和发现

    java的垃圾回收与内存泄露的关系:[新手可忽略不影响继续学习] 马克-to-win:上一节讲了,(i)对象被置成null.(ii)局部对象(无需置成null)当程序运行到右大括号.(iii)匿名对象 ...

  3. Git本地上传口令

    $ cd /d/GitProject  (进入要上传的文件的文件夹) $ git pull                 (更新本地库) $ git add .                (添加 ...

  4. Python中用函数实现代码的复用

    # Python中用函数实现代码复用 """ def funcname(paras): statements return [expression] 关于函数定义说明如下 ...

  5. int bool str

    一. python的基本数据类型 1. int 整数 2. bool 布尔.  判断.  if  while 3. str  字符串 ,一般存放小量的数据 4. list  列表. 可以存放大量的数据 ...

  6. ADO访问Excel

    需要安装驱动:Microsoft Access Database Engine,可搜索下载,有64位和32位之分. 随便新建一个后缀名为udl的文件,双击打开.注意,现如今一般都是64位系统,双击打开 ...

  7. 认识python-个人笔记篇

    认识python 1 .python 的发展历史 一种广泛使用的解释型.高级编程.通用型编程语言,由"龟叔"吉多·范罗苏姆创造,第一版发布于1991年. Python的设计哲学强调 ...

  8. HMS Core 6.4.0版本发布公告

    支持转化事件回传至华为应用市场商业推广,便捷归因,实时调优: 卸载分析新增卸载前路径分析,深度剖析卸载根因. 查看详情 新增关键帧能力,通过关键帧点可实现图片.文字等位置移动.旋转等动态效果,比如文字 ...

  9. 使用 Bitnami PostgreSQL Docker 镜像快速设置流复制集群

    bitnami-docker-postgresql 仓库 源码:bitnami-docker-postgresql https://github.com/bitnami/bitnami-docker- ...

  10. Oracle 定时任务增删改查

    创建 -- 创建定时任务 DECLARE jobno NUMBER; BEGIN dbms_job.submit ( jobno, -- 定时器ID,系统自动获得 'PRC_INSERT;', -- ...