按照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<len;i++)
SAM_add(s[i]-'a');
}
}