码迷,mamicode.com
首页 > 其他好文 > 详细

学习笔记(SAM)

时间:2018-01-14 17:45:14      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:log   oid   markdown   div   blog   link   down   学习   函数   

后缀自动机学习笔记

性质
  • 首先,你最好认为每条边是一个字母,每个节点代表一个单词(从t0走到这个点即是此单词的一个后缀)。
  • 所有的正向边,从t0出发沿着nex形成的所有正向边构成一个DEG图,而所有的反向边,即link构成一颗t0为根的树,显然,此树上所有点到根形成的后缀都会被其儿子到根形成的后缀所包含
算法实现
  • 首先写个自定义函数,一般都叫sa_extend()
  • 我们默认根t0是0,他的link(父亲)为-1。
  • 首先新申请一个节点cur,我每次将上一个节点叫做last,先将len[cur]=len[last]+1,(len数组代表其到根节点的距离)
  • 然后沿着last节点一直往上跳(如果该节点没有你要加的那个节点的儿子),将所有这些节点nex那个字母都连到cur上
  • 如果一直跳到-1了,就将cur的link连到0上,并退出.
  • else
  • 如果当前节点(p)此儿子(q)的len==当前节点len+1,就将cur的link设为q
  • else
  • 申请一个新的节点(一般叫clone),将clone的len设为此节点len+1,并将q的所有信息复制给clone,将q与cur的link都设为clone,继续沿着p往上跳,将所有有儿子q的点改为clone。
代码实现
void sa_extend(int x)
{
    int cur=++sz;
    len[cur]=len[last]+1;
    int p;  
    for(p=last;p!=-1&&!nex[p][x];p=link[p])nex[p][x]=cur;
    if(p==-1)link[cur]=0;
    else
    {
        int q=nex[p][x];
        if(len[p]+1==len[q])link[cur]=q;
        else
        {
            int clone=++sz;
            len[clone]=len[p]+1;        
            For(i,0,25)nex[clone][i]=nex[q][i];
            link[clone]=link[q];
            for(;p!=-1&&nex[p][x]==q;p=link[p])nex[p][x]=clone;
            link[q]=link[cur]=clone;
        }

    }
    last=cur;
}

学习笔记(SAM)

标签:log   oid   markdown   div   blog   link   down   学习   函数   

原文地址:https://www.cnblogs.com/dengyixuan/p/8283682.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!