后缀自动机学习笔记
性质
- 首先,你最好认为每条边是一个字母,每个节点代表一个单词(从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;
}