char s[N]; int sa[N],rank[N],h[N],n,m,len; int cnt[N],val[N],stk[N],_val[N],top; bool issame(int a,int b,int hl) { if(val[a]!=val[b])return 0; if(a+hl>len&&b+hl>len)return 1; if(a+hl<len&&b+hl<len)return val[a+hl]==val[b+hl]; return 0; } void SA(int lim) { int i,j,k,hl; for(i=0;i<lim;i++)cnt[i]=0; for(i=0;i<len;i++)cnt[val[i]=s[i]-'a']++; for(i=1;i<lim;i++)cnt[i]+=cnt[i-1]; for(i=len-1;i>=0;i--)sa[--cnt[val[i]]]=i; for(k=1;;k++) { top=0,hl=1<<(k-1); for(i=0;i<len;i++)if(sa[i]+hl>=len)stk[top++]=sa[i]; for(i=0;i<len;i++)if(sa[i]>=hl)stk[top++]=sa[i]-hl; for(i=0;i<lim;i++)cnt[i]=0; for(i=0;i<len;i++)cnt[val[i]]++; for(i=1;i<lim;i++)cnt[i]+=cnt[i-1]; for(i=len-1;i>=0;i--)sa[--cnt[val[stk[i]]]]=stk[i]; for(lim=i=0;i<len;lim++) { for(j=i;j<len-1&&issame(sa[j],sa[j+1],hl);j++); for(;i<=j;i++)_val[sa[i]]=lim; } for(i=0;i<len;i++)val[i]=_val[i]; if(lim==len)break; } for(i=0;i<len;i++)rank[sa[i]]=i; for(i=0;i<len;i++) { if(k)k--; if(!rank[i])continue; while(s[i+k]==s[sa[rank[i]-1]+k])k++; h[rank[i]]=k; } }