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

[OI笔记]后缀自动机

时间:2018-01-28 23:22:54      阅读:316      评论:0      收藏:0      [点我收藏+]

标签:targe   ref   size   更新   情况   文化课   set   blog   blank   

本来没打算写的,不过想想看后缀自动机的理论看了两三天了才有点懂(我太傻了)…下周期末考的话大概要去复习一下文化课感觉回来又要忘得差不多,还是开篇blog记一下好了。

 

相关的资料:

cls当年的课件:2012年noi冬令营陈立杰讲稿

一篇不错的blog:http://www.cnblogs.com/meowww/p/6394960.html

 

因为博主比较懒(菜)所以这里就大概记一些关键的东西(其实也就只复述了一遍建SAM的过程,大概在cls课件40页左右的地方)。

用$p$表示$p=ST(T)$且$Right(p)=\{Lenght+1\}$的点(代码里用$last$记录),对于字符串$T$的SAM,我们在后面加入一个新的字符$x$,新建$np=ST(Tx),val[np]=val[p]+1$,对$p$所有没有$x$标号的祖先$v$,令$tr[v][x]=np$,也就是连向我们新加的点。

就这样找到第一个有$x$标号的祖先$v_p$,这里有几种情况。如果没有找到这样的$v_p$直接令$suf[np]=root$(根作为$np$的父亲),然后就可以结束了。否则令$q=tr[v_p][x]$,这时候如果$val[v_p]+1=val[q]$的话直接让$suf[np]=q$然后结束,但是如果不行的话就有点麻烦了,这时候我们要再建一个点$nq:tr[nq][*]=tr[q][*]$,然后$suf[nq]=suf[q],suf[q]=suf[np]=nq$,最后对所有$tr[v][x]==q$的祖先$v$都改成$tr[v][x]=nq$。

最后当然不要忘记更新$last$。

构造大概就是这样子啦。

inline int newNode(int x)
{
    val[++cnt]=x;return cnt;
}
inline void insert(int x)
{
    int p=last,np=newNode(val[p]+1);memset(tr[np],0,sizeof tr[np]);
    while(p&&!tr[p][x])tr[p][x]=np,p=suf[p];
    if(!p)suf[np]=1;
    else
    {
        int q=tr[p][x];
        if(val[q]==val[p]+1)suf[np]=q;
        else
        {
            int nq=newNode(val[p]+1);
            memcpy(tr[nq],tr[q],sizeof tr[nq]);
            suf[nq]=suf[q];suf[np]=suf[q]=nq;
            while(p&&tr[p][x]==q)tr[p][x]=nq,p=suf[p];
        }
    }
    last=np;
}

写起来还是挺短的

[OI笔记]后缀自动机

标签:targe   ref   size   更新   情况   文化课   set   blog   blank   

原文地址:https://www.cnblogs.com/yoooshinow/p/8372722.html

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