其他分享
首页 > 其他分享> > 后缀自动机

后缀自动机

作者:互联网

(本文不适合初学者)

SAM

前置概念

构造

namespace SAM{
	struct node{
		int len,link,nxt[26];
	}a[N<<1];
	int las=0,tot=0;
	inline void init() {a[0].link=-1;}
	inline void insert(int x) {
		int cur=++tot;cnt[cur]=1;
		a[tot].len=a[las].len+1;
		int p=las;
		while(p!=-1 && !a[p].nxt[x]) {a[p].nxt[x]=cur;p=a[p].link;}
		if(p==-1) a[cur].link=0;
		else {
			int q=a[p].nxt[x];
			if(a[p].len+1==a[q].len) a[cur].link=q;
			else {
				int clone=++tot;
				a[clone]=a[q];
				a[clone].len=a[p].len+1;
				a[q].link=a[cur].link=clone;
				while(p!=-1 && a[p].nxt[x]==q) {a[p].nxt[x]=clone;p=a[p].link;}
			}
		}
		las=cur;
	}
}

(注意空间要开两倍)

LG P3804 【模板】后缀自动机 (SAM)

性质

应用

广义 SAM

namespace SAM{
	struct node{
		int link,len,nxt[26];
	}a[N<<1];
	int tot,las=0;
	inline void init() {a[0].link=-1;}
	inline void insert(int x) {
		if(a[las].nxt[x]) {
			int cur=a[las].nxt[x];
			if(a[las].len+1==a[cur].len) return las=cur,void();
			int clone=++tot;
			a[clone]=a[cur];a[clone].len=a[las].len+1;
			a[cur].link=clone;
			int p=las;
			while(p!=-1 && a[p].nxt[x]==cur) a[p].nxt[x]=clone,p=a[p].link;
			return las=clone,void();
		}
		int cur=++tot;
		a[cur].len=a[las].len+1;
		int p=las;
		while(p!=-1 && !a[p].nxt[x]) a[p].nxt[x]=cur,p=a[p].link;
		if(p==-1) a[cur].link=0;
		else {
			int q=a[p].nxt[x];
			if(a[p].len+1==a[q].len) a[cur].link=q;
			else {
				int clone=++tot;
				a[clone]=a[q];
				a[clone].len=a[p].len+1;
				a[q].link=a[cur].link=clone;
				while(p!=-1 && a[p].nxt[x]==q) a[p].nxt[x]=clone,p=a[p].link;
			}
		}
		las=cur;
	}
}using namespace SAM;

LG P6139 【模板】广义后缀自动机(广义 SAM)

性质

LG P5357 【模板】AC 自动机(二次加强版)

参考代码

	int p=0,fl=1;
	FOR(i,1,len) {
		int x=S[i]-'a';
		while(p!=-1 && !a[p].nxt[x]) p=a[p].link,fl=1;
		if(p==-1) p=0;
		else {
			if(a[p].len+1!=a[a[p].nxt[x]].len)  fl=0;
			p=a[p].nxt[x];
			if(!fl) ++num[a[p].link];
			else ++num[p];
		}
	}

应用

标签:子串,每个,SAM,后缀,len,集合,自动机,节点
来源: https://www.cnblogs.com/kzos/p/16343090.html