后缀自动机构建图解

摘要:
于是需要把这个等价类分成和两个点,然后把接到上:如图,a现在也变成了红圈点,这就是新建点的过程。やったぜ~感觉第一次真正理解了后缀自动机,图有点丑见谅啦
目录

后缀自动机构建图解

我是在这学的:https://www.luogu.com.cn/blog/Kesdiael3/hou-zhui-zi-dong-ji-yang-xie

感觉作者画的图有点难理解,而且讲到了所以来画一画,方便复习。看本文前最好先把上面那个看一遍!

此处是从右往左增量,画图时没注意

代码:(注意case的位置)

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');
}

case1

首先处理好parent树信息:

int p=las;int np=las=++tot;
dian[np].len=dian[p].len+1;

case1就是直接接到根上,下面为了方便理解把所有压缩的点都画出来了

后缀自动机构建图解第1张

实现方法(参照代码):

for(;p&&!dian[p].ch[c];p=dian[p].fa)dian[p].ch[c]=np;
    if(!p)dian[np].fa=1;//以上为case 1
  1. 新加进来的字符变量名为 (c)
  2. 新建点 (np(11))
  3. 查看前面的点有没有能接上的,即有c这条出边
  4. 这种情况为到根都没有,直接接上根点(1)

case2

前面有这个出边而且长度等于新后缀减一,此时直接连到后面。

这种情况很简单,因为只能是前一个后缀长度才能相差一

后缀自动机构建图解第2张

实现方法:

int q=dian[p].ch[c];
if(dian[q].len==dian[p].len+1)dian[np].fa=q;//以上为case 2
  1. (q(2)) 为前面的有出边为 (c) 字符(此处 (c) 为'a')的点
  2. 长度符合,能接上,把(np(3))直接接到(q(2))

case3

回到case1的图,此时后缀自动机上真实存在的点只是红圈的点

未命名.png

现在加入 (acabd),发现有根有 (a) 的出边,但是不能直接接上,因为实际上不存在5这个点。

也可以理解为5是被压缩的点。

于是需要把 (abd) 这个等价类分成 (a)(abd) 两个点 ,然后把 (acabd) 接到 (a) 上:

未命名.png

如图,a现在也变成了红圈点,这就是新建点的过程。

实现方法:

 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
 }
  1. 新建点 (nq(5))
  2. (q(7)) 的信息传给 (nq(5)) :包括转移,parent树上父亲,等价类最大长度
  3. (nq(5)) 最大长度此时为 (len(p(1))+1=2),因为加了新增的字符 (a)
  4. (q(7))(np(15)) 的父亲置为 (nq)
  5. 根据转移边要尽量近的原则,把原先a转移为 (q(7)) 的转移边连到 (nq(5)) 上(从 (p(1)) 开始)

做完了!やったぜ ~

感觉第一次真正理解了后缀自动机,图有点丑见谅啦

免责声明:文章转载自《后缀自动机构建图解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇003 机器学习中的基础知识文件上传(FileUpload)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

回文自动机做题小结

模板 求以每个位置结尾的回文串的数量,加密输入 就是回文自动机节点的(len)数组,对应的是最长回文后缀 双倍回文 求形如(AA^rAA^r) 方法一:建立(fail)树,然后对每个(len)是偶数的点,在子树内找有没有长度为(2*len)的点,通过打标记做到(O(n)) 方法二:求一个与(fail)数组对应的(tran)数组,含义为长度不超过(frac{...

字符串匹配算法

一、简介 文本信息可以说是迄今为止最主要的一种信息交换手段,而作为文本处理中的一个重要领域——字符串匹配,就是我们今天要说的话题。(原文还特意提及文本数据数量每18个月翻一番,以此论证算法必须要是高效的。不过我注意到摩尔定律也是18个月翻番,这正说明数据的增长是紧紧跟随处理速度的,因此越是使用高效的算法,将来待处理的数据就会越多。这也提示屏幕前的各位,代码...

「专题总结」后缀自动机

后缀自动机重点在于性质,东西很多注意区分概念。 后缀自动机是一个(DAG),从根开始的路径能够识别(S)的每个后缀(子串),一定不存在一条从根开始的路径能够识别不是S的子串。 点:每个节点代表了一个(endpos)类,从根到该节点的所有字符串在S中的出现位置相同,一个点代表的(endpos)集相同的各个串之间有后缀关系且连续,暂且称这些串的集合为(P)。...

「学习笔记」AC自动机

还记得2019年暑假,gy在英乐华翻开ybt提高篇的目录 概述 通常来讲,KMP 算法用来处理单模式串匹配问题。而若要处理多模式串的问题,就要引出 AC自动机 。 AC自动机 是以 Trie 的结构为基础,结合 KMP 的思想建立的。 步骤 将所有模式串构建成一棵 Trie 树 对 Trie 上所有节点构造失配指针(最长后缀) 利用失配指针对主串进行匹配...