首页 > 其他分享 >【博客】后缀自动机

【博客】后缀自动机

时间:2024-02-15 20:14:08浏览次数:25  
标签:子串 后缀 博客 endpos 字符串 自动机 任意

后缀自动机

在阅读了众多大佬的博客之后 终于对后缀自动机有了初步理解 简单整理一下学习成果


大佬文献如下

史上最通俗的后缀自动机详解(写的真的好)

后缀自动机 (SAM) - OI Wiki (OI-wiki yyds)

后缀自动机

后缀自动机SAM-CSDN博客


引入

我们可以建立一个字典树 将原串的所有子串表示在一张有向无环图(DAG)上面

用一张大佬的图

image

我们能够直观地总结出来的性质有:

  1. 有一个源点,若干个终止点。边代表在目前的字符串后加上的字母。从源点到任意一个节点的任意路径可以形成一个字符串。
  2. 源点到任意节点的任意路径形成的字符串均为原串子串。从源点到任意节点的任意路径不能形成的字符串均为原串子串。(简单来说,这个图可以表示,且仅可以表示出原串的所有子串)
  3. 从源点到任意终止节点的任意路径形成的字符串均为原串​后缀​。
  4. 从源点出发的任意两条不同路径形成的字符串不相同。

但是这样建立的DAG点数过多$(n^2)$
所以后缀自动机出现了
它建立的DAG把原DAG上的一些可以合并的点合并了


定义

结束位置endpos(学SAM离不开它)

对于一个子串,它在原串中可能出现在若干的位置。而一个子串$p$出现的这些位置的右端点标号组成的集合,我们称之为$endpos(p)$

例如原串为abcab时,$endpos(ab)={\ 2,5 \ }\ $

然后有很多性质

1.如果两个子串endpos的相同,则其中子串一个必然为另一个的后缀

2.对于任意两个字串 他们的endpos不是包含关系 就是交集为空的关系

3.对于endpos相同的子串,我们将它们归为一个endpos等价类。一个endpos等价类内的串的长度连续

4.endpos等价类的个数为O(n)

对于在p前添加一个字符,我们可以认为是对一个原集合进行分割,分割得到几个新的集合,且保留原集合。所有endpos等价类依靠这种分割关系,恰好可以构造出一个树形结构。于是类之间有了父子关系。这棵树便是parent tree,它是自动机的关键

还是大佬的图

image

还有好多性质......

总之 这些性质保证了后缀自动机的可行性

再总之 我们最后建出的自动机有以下性质

  1. 有一个源点,边代表在当前字符串后增加一个字符。
  2. 每个点代表一个endpos等价类,到达一个点的路径形成的子串必须属于此点的类。
  3. 点之间有父子关系,到达点i的所有字符串的长度都必然大于到达fa(i)的所有字符串的长度,且到fa(i)的任意一字符串必为到达i的任意一字符串的后缀。

构造

构造的过程大概是这样的

假设我们新加入了边c
当前跳到的点为p

1.新建一个点 然后不断往父节点跳 (条件是不跳出根节点 并且p没有边c)跳到头有三种情况

2.分别处理三种情况

Case 1:p跳到了根节点 没有转移边c 那么连新点和根节点

Case2:p在有边c的点停下了 令q为p经过c到达的节点 且len(q)=len(p)+1 那么连新点和q

Case3:len(q)!=len(p)+1 将q裂开成新结点 继承父子关系

struct NODE
{
    int ch[26];
    int len,fa;
    NODE(){memset(ch,0,sizeof(ch));len=0;}
}dian[MAXN<<1];
int las=1,tot=1;
void add(int c)
{
    int p=las;int np=las=++tot;
    dian[np].len=dian[p].len+1;
    for(;p&&!dian[p].ch[c];p=dian[p].fa)dian[p].ch[c]=np; //不断跳
    if(!p)dian[np].fa=1;//以上为case 1
    else
    {
        int q=dian[p].ch[c];
        if(dian[q].len==dian[p].len+1)dian[np].fa=q;//以上为case 2
        else
        {
            int nq=++tot;dian[nq]=dian[q];
            dian[nq].len=dian[p].len+1;
            dian[q].fa=dian[np].fa=nq; 
            for(;p&&dian[p].ch[c]==q;p=dian[p].fa)dian[p].ch[c]=nq;//以上为case 3
        }
    }
}
char s[MAXN];int len;
int main()
{
    scanf("%s",s);len=strlen(s);
    for(int i=0;i<len;i++)add(s[i]-'a');
}

然后我们就建好了后缀自动机

它可以解决很多问题

比如判断A是否是B的子串 求不同子串的个数等


终!于!写!完!了! (咆哮

完结撒花

Let It Out - 陈奕迅 好好听

标签:子串,后缀,博客,endpos,字符串,自动机,任意
From: https://www.cnblogs.com/zysssss/p/18016530

相关文章

  • 【博客】网络流&&费用流
    网络流前言当听到网络流量之后感觉是在充话费网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关。它模拟了水流从起点经过复杂的网络流向终点的过程就像自来水厂的水经过无数根水管子流到了家里而最大流就是最多有多少水流到了家里算法流程EK......
  • 欢迎来到 HZJ 的博客园
    前期提要原先我的博客是建立在洛谷上的原洛谷博客,但最近洛谷走向国际化,要把洛谷改成文章区,要经过一定时间的系统维护。我为了避免长时间的洛谷博客维护,就迁移到了博客园。我最近研究了一下博客园,其实洛谷博客要比博客园稍逊一筹的。博客园有\(LaTeX\)、有代码格式,有网站引......
  • 后缀自动机
    后缀自动机很毒瘤的字符串数据结构,但是我觉得多在脑子里梳理几遍后,比后缀数组好用多了(这里跳过几乎所有证明,除了对后面理解有影响的,因为我认为这些不重要也学不会主要记录对做题有帮助的核心性质字符串的SAM可以理解为这个字符串的所有子串的压缩形式定义SAM是一个接受......
  • AC自动机
    AC自动机它具体而言是实现字符串多模匹配的相比KMP,它能解决找出多个字符串在文章中出现的位置(KMP只是1-1)你可以认为它是KMP(思想)+Trie字典树不过和KMP一样,在查找时它加入了fail数组,fail[i]记录以i为结尾的后缀在Trie中其他字符串上的最长前缀听起来很绕,但可以理解一下优化原......
  • 后缀数组
    后缀数组后缀数组利用倍增思想求出sarank数组然后利用这两个数组求height最后利用height解决一些问题所以啥是sarankheight啊?算法流程定义1.后缀数组sa将按字典序排序后的后缀的开头位置顺次放入了sa中换个说法就是sa[i]表示字典序排名为i的后缀的开头的下标2.......
  • 关于“博客园”经济脱困的一些看法
    作为和CSDN同为中国IT领域最大的技术博客网站,一个赚的盆满钵满,一个到了穷的要关门大吉了,这个发展也是耐人寻味的。不得不说,之所以自己选择在博客园而不是CSDN,其主要原因就是没有那些讨厌的广告,使用起来十分简洁和方便。但是这个博客园发展到如今这个难以维继的局面也是没有预料到......
  • Suffix Array:后缀数组学习笔记
    后缀排序后缀排序,顾名思义就是给后缀排个序。朴素做法是\(O(n^2\logn)\)的,无法接受。因此诞生了基于倍增思想的后缀排序算法。其中倍增思想在集训队论文中讲得很好,在此不再赘述。这里主要讲代码实现。constintN=2e6+10;chars[N];intn,m,sa[N],rk[N],tp[N],b[N];void......
  • 博客园配置
    Awescnb1.安利几款好看的博客园主题-CryFace-博客园(cnblogs.com)2.Awescnb手册|Awescnb(gitee.io)3.Awescnb配置选项(yuque.com)代码高亮显示行号Mac风格代码字体:FiraCode主题:atom-one-dark博客侧边栏公告无页面定制CSS代码禁用模板默认CSS#......
  • 给博客园捐些款:发个阿里云广告,对园子脱困很重要:阿里云上部署幻兽帕鲁
    相关:https://www.cnblogs.com/cmt/p/17995766由于博客园官方比较poor,而我也比较poor,但是考虑到不要让博客园关门了,毕竟这么多年了,而且自己在这上面的东西也蛮多的,搬家也挺费劲的,最为关键的是自己不喜欢别家的那种全是广告和充费的那种,动不动就要付费的那种,最终还是决定在自己......
  • 记录一下自定义博客园主题过程
    前言以前使用的都是默认的博客园主题,最近刚好有空,着手定制以下自己的博客园主题。最终效果参考当前的博客,如果看不到则需要在博客园首页头像处悬停关闭简洁模式思路是尽量保持原有结构,不进行破坏性改动,以css样式为主(当前只添加了两个js方法用于主题切换和判断是否在随笔阅读......