SAM学习笔记

按照hihocoder上的SAM的教程学习了一波SAM

http://hihocoder.com/contest/hiho127

http://hihocoder.com/contest/hiho128

http://hihocoder.com/contest/hiho129

http://hihocoder.com/contest/hiho130

http://hihocoder.com/contest/hiho131

http://hihocoder.com/contest/hiho132

http://hihocoder.com/contest/hiho133

搞了这么多年ACM终于会一个字符串算法了


模版:

namespace SAM
{
	const int CHAR=26;
	const int MAXN=1e6+5;
	struct SAM_Node
	{
		SAM_Node *fa,*next[CHAR];
		int mx,mi;//当前状态下最长的子串和最短的子串
		int id;
		SAM_Node(){}
		SAM_Node(int _mx)
		{
			fa=0;
			mx=_mx;
			memset(next,0,sizeof(next));
		}
	};
	SAM_Node SAM_node[MAXN*2],*SAM_root,*SAM_last;
	int SAM_size;
	SAM_Node *newSAM_Node(int len)
	{
		SAM_node[SAM_size]=SAM_Node(len);
		SAM_node[SAM_size].id=SAM_size;
		return &SAM_node[SAM_size++];
	}
	SAM_Node *newSAM_Node(SAM_Node *p)
	{
		SAM_node[SAM_size]=*p;
		SAM_node[SAM_size].id=SAM_size;
		return &SAM_node[SAM_size++];
	}
	void SAM_init()
	{
		SAM_size=0;
		SAM_root=SAM_last=newSAM_Node(0);
	}
	void SAM_add(int c)
	{
		SAM_Node *u=SAM_last,*z=newSAM_Node(u->mx+1);
		SAM_last=z;
		for(;u&&!u->next[c];u=u->fa)
			u->next[c]=z;
		if(!u)
		{
			z->fa=SAM_root;
			z->mi=1;
			return;
		}
		SAM_Node *x=u->next[c];
		if(x->mx==u->mx+1)//不用拆分
		{
			z->fa=x;
			z->mi=x->mx+1;
			return;
		}
		SAM_Node *y=newSAM_Node(x);//拆分x
		y->mx=u->mx+1;
		x->fa=y;x->mi=y->mx+1;
		z->fa=y;z->mi=y->mx+1;
		for(;u&&u->next[c]==x;u=u->fa)
			u->next[c]=y;
		y->mi=y->fa->mx+1;
	}
	void SAM_build(char *s)
	{
		SAM_init();
		int len=strlen(s);
		for(int i=0;i

你可能感兴趣的:(学习笔记)