SAM初步

SAM(Suffix Automaton),后缀自动机。

SAM是种十分神奇的数据结构,我认为他的主要神奇之处,在于最大限度的利用了分类思想。

SAM上有两种边,代表两种转移方式。

一种是树边,一种是转移边,树边代表对SAM对子串出现位置的分类,转移边代表当前节点代表的子串加入字符后的节点的分类。

由于子串的出现位置的集合或者是子集关系,或者无交集,可以证明状态数是O(n)的。

在有了这些东西后,SAM基本可以搞出关于字符串的所有问题。

SAM有句很经典的话:出现次数向父亲传递,接收串数从儿子获取。

构造模板:

struct sam{
	int pre[maxn],c[maxn][26],len[maxn],q,p,nq,np;
	int cnt,now;
	sam(){mem1(pre,0);mem1(c,0);mem1(len,0);cnt=now=1;}
	void expend(int x){
		p=now,np=++cnt;
		len[np]=len[now]+1;now=np;
		while(p&&!c[p][x])c[p][x]=np,p=pre[p];
		if(!p)pre[np]=1;
		else {
			q=c[p][x];
			if(len[q]=len[p]+1)pre[np]=q;
			else {
				len[nq=++cnt]=len[p]+1;
				mem2(c[nq],c[q]);
				pre[nq]=pre[q];
				pre[np]=pre[q]=nq;
				while(p&&c[p][x]==q)c[p][x]=nq,p=pre[p];
			}
		}
	}
	void build(char* s){
		int n=strlen(s+1);
		up(i,1,n)expend(s[i]);
	}
}SAM;

  

原文地址:https://www.cnblogs.com/chadinblog/p/6418604.html