没错,一定是无聊到一定境界的人才能干出这种事情。
这个无聊的zcysky已经不满足于用后缀平衡树求sa了,他想用sam试试。
我们回顾下sam的插入过程,如果我们从最后一个state沿着suffix link向上爬parent tree
那么我们就可以遍历这个sam的所有后缀。
那么我们把插入的时候经历的state全都标记下来,并且记录下这个state对应的序号
在对parent tree进行dfs的时候先序遍历一下就可以了。
#include<bits/stdc++.h> #define N 300010 using namespace std; int n,c[N],tot,tota,sacnt,top=0,cnt=0; int last=1,fa[N],ch[N][26],l[N],vis[N],head[N]; int r[N],sa[N],rk[N],h[N]; char s[N]; struct state{int x,y,v;}q[N]; struct Edge{int u,v,next;}G[N<<1]; inline void addedge(int u,int v){ G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot; } void dfs(int u){ if(r[u])sa[++sacnt]=r[u]; for(int i=head[u];i;i=G[i].next)dfs(G[i].v); } void ins(int c,int pos){ int p=last,np=++cnt;last=np;l[np]=l[p]+1;r[np]=pos; for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np; if(!p)fa[np]=1; else{ int q=ch[p][c]; if(l[p]+1==l[q])fa[np]=q; else{ int nq=++cnt;l[nq]=l[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q];fa[np]=fa[q]=nq; for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq; } } } int main(){ int f=0; scanf("%s",s+1);n=strlen(s+1); vis[1]=last=cnt=1; for(int i=n;i;i--)ins(s[i]-'a',i); for(int i=1;i<=cnt;i++)if(r[i]&&!vis[i]) for(int pos=n,j=i;!vis[j];vis[j]=1,j=fa[j],--pos){ pos=pos-l[j]+l[fa[j]]+1;q[++top]=(state){fa[j],j,s[pos]-'a'}; } for(int i=1;i<=top;i++)c[q[i].v]++; for(int i=1;i<26;i++)c[i]+=c[i-1]; for(int i=top;i;i--)rk[c[q[i].v]--]=i; for(;top;top--)addedge(q[rk[top]].x,q[rk[top]].y); dfs(1); for(int i=1;i<=n;i++)printf("%d ",sa[i]);puts(""); for(int i=1;i<=n;i++)rk[sa[i]]=i; for(int i=1;i<=n;i++){ int f=max(h[rk[i-1]]-1,0); for(int j=sa[rk[i]-1];s[i+f]==s[j+f];f++); h[rk[i]]=f; } for(int i=2;i<=n;i++)printf("%d ",h[i]); }
就这样,用sam就把这题水过去了~