代码
//确认maxn大小,一般是原字符串长度最大值的2倍,然后是init(),最后是一个一个的字符插入, //转化成对应的数字,调用Insert函数,可支持在线。 struct SAM { int ch[maxn][26]; int pre[maxn],step[maxn]; int last,id; void init() { last=id=0; memset(ch[0],-1,sizeof(ch[0])); pre[0]=-1; step[0]=0; } void Insert(int c) { int p=last,np=++id; step[np]=step[p]+1; memset(ch[np],-1,sizeof(ch[np])); while(p!=-1&&ch[p][c]==-1) ch[p][c]=np,p=pre[p]; if(p==-1) pre[np]=0; else { int q=ch[p][c]; if(step[q]!=step[p]+1) { int nq=++id; memcpy(ch[nq],ch[q],sizeof(ch[q])); step[nq]=step[p]+1; pre[nq]=pre[q]; pre[np]=pre[q]=nq; while(p!=-1&&ch[p][c]==q) ch[p][c]=nq,p=pre[p]; } else pre[np]=q; } last=np; /* //查询出现至少K次的子串数量 while(np!=-1&&num[np]<K) //没有达到K次的就加1 { num[np]++; if(num[np]>=K) ans+=step[np]-step[pre[np]]; //加上答案 np=pre[np]; } */ } /* int GetCnt() //可查询有多少种不同的子串 { int ret=0; for(int i=id;i>=1;i--) ret+=step[i]-step[pre[i]]; return ret; } */ }sam;