变量
- int tot:节点个数。
- int tpos:字符个数。
- int now:现在走到了哪个点。
- int rem:最长隐式后缀长度。
- int inf:正无穷。
- int s[i]:插入的字符。
- Node a[p]:节点 p 的信息。
- int a[p].link:节点 p 的 link 链接,指向从根到当前节点的字符串的最大后缀所在的点。
- int a[p].st:节点 p 代表的一段字符串的起点位置。
- int a[p].len:节点 p 代表的一段字符串的长度。
- int a[p].len:节点 p 代表的子串集合中最长的长度。
- int a[p].ch[c]:节点 p 加上字符 c 后的儿子。
函数
- SufTree():初始化。
- int make(int st,int len):新建起点为 st 长度为 len 的节点。
- void extend(int x):在后缀树的字符串末尾加入字符 x。
代码
struct SufTree{
int tot,tpos,now,rem,inf;
int s[N];
struct Node{
int link,st,len,ch[27];
}a[N<<1];
SufTree(){
tot=now=1,tpos=rem=0;
a[0].len=inf=1e9;
}
int make(int st,int len){
a[++tot].link=1;a[tot].st=st;
a[tot].len=len;return tot;
}
void extend(int x){
s[++tpos]=x;rem++;
for(int lst=1;rem;){
while(rem>a[a[now].ch[s[tpos-rem+1]]].len)
rem-=a[now=a[now].ch[s[tpos-rem+1]]].len;
int p=a[now].ch[s[tpos-rem+1]],q;
int c=s[a[p].st+rem-1];
if(!p||x==c){
a[lst].link=now;lst=now;
if(!p)a[now].ch[s[tpos-rem+1]]=make(tpos,inf);
else break;
}
else{
q=make(a[p].st,rem-1);
a[q].ch[c]=p;
a[q].ch[x]=make(tpos,inf);
a[p].st+=rem-1;a[p].len-=rem-1;
a[lst].link=a[now].ch[s[tpos-rem+1]]=q;
lst=q;
}
if(now==1)rem--;else now=a[now].link;
}
}
}st;