template/ShinriiTin/SA_IS

template<size_t size>
struct SuffixArray{
    bool type[size<<1];
    int bucket[size],bucket1[size];
    int sa[size],rk[size],ht[size];
    inline bool isLMS(const int i,const bool *type){return i>0&&type[i]&&!type[i-1];}
    template<class T>
    inline void inducedSort(T s,int*sa,int len,int sigma,int bucketSize,bool*type,int*bucket,int*cntbuf,int*p){
        memset(bucket,0,sizeof(int)*sigma),memset(sa,-1,sizeof(int)*len);
        register int i;
        for(i=0;i<len;++i)++bucket[s[i]];
        cntbuf[0]=bucket[0];
        for(i=1;i<sigma;++i)cntbuf[i]=cntbuf[i-1]+bucket[i];
        for(i=bucketSize-1;~i;--i)sa[--cntbuf[s[p[i]]]]=p[i];
        for(i=1;i<sigma;++i)cntbuf[i]=cntbuf[i-1]+bucket[i-1];
        for(i=0;i<len;++i)if(sa[i]>0&&!type[sa[i]-1])sa[cntbuf[s[sa[i]-1]]++]=sa[i]-1;
        cntbuf[0]=bucket[0];
        for(i=1;i<sigma;++i)cntbuf[i]=cntbuf[i-1]+bucket[i];
        for(i=len-1;~i;--i)if(sa[i]>0&&type[sa[i]-1])sa[--cntbuf[s[sa[i]-1]]]=sa[i]-1;
    }
    template<typename T>
    inline void sais(T s,int*sa,int len,bool*type,int*bucket,int*bucket1,int sigma) {
        register int i,j,x;
        int bucketSize=0,cnt=0,p=-1,*cntbuf=bucket+sigma;
        type[len-1]=1;
        for(i=len-2;~i;--i)type[i]=s[i]<s[i+1]||s[i]==s[i+1]&&type[i+1];
        for(i=1;i<len;++i)if(type[i]&&!type[i-1])bucket1[bucketSize++]=i;
        inducedSort(s,sa,len,sigma,bucketSize,type,bucket,cntbuf,bucket1);
        for(i=bucketSize=0;i<len;++i)if(isLMS(sa[i],type))sa[bucketSize++]=sa[i];
        for(i=bucketSize;i<len;++i)sa[i]=-1;
        for(i=0;i<bucketSize;++i){
            x=sa[i];
            for(j=0;j<len;++j) {
                if(p==-1||s[x+j]!=s[p+j]||type[x+j]!=type[p+j]){cnt++,p=x;break;}
                else if(j>0&&(isLMS(x+j,type)||isLMS(p+j,type)))break;
            }
            x=(~x&1?x>>1:x-1>>1);
            sa[bucketSize+x]=cnt-1;
        }
        for(i=j=len-1;i>=bucketSize;--i)if(~sa[i])sa[j--]=sa[i];
        int *s1=sa+len-bucketSize,*bucket2=bucket1+bucketSize;
        if(cnt<bucketSize)sais(s1,sa,bucketSize,type+len,bucket,bucket1+bucketSize,cnt);
        else for(i=0;i<bucketSize;++i)sa[s1[i]]=i;
        for(i=0;i<bucketSize;++i)bucket2[i]=bucket1[sa[i]];
        inducedSort(s,sa,len,sigma,bucketSize,type,bucket,cntbuf,bucket2);
    }
    template<typename T>
    inline void getHeight(T s,int len,int*sa){
        register int i,j,k;
        for(i=k=0;i<len;++i){
            if(!rk[i])k=0;
            else{
                if(k>0)--k;
                j=sa[rk[i]-1];
                while(i+k<len&&j+k<len&&s[i+k]==s[j+k])++k;
            }
            ht[rk[i]]=k;
        }
    }
    template<class T>
    inline void init(T s,int len,int sigma) {
        sais(s,sa,len,type,bucket,bucket1,sigma);
        for(int i=1;i<len;++i)rk[sa[i]]=i;
        getHeight(s,len,sa);
    }
};

注意事项:字符串从 0 开始,init时,len需要传入字符串长度n+1,simga需要传入字符集大小,init完毕后得到sa数组,0到n共n+1个后缀排序后的结果(sa[0]总是表示空串),以及rk数组和ht数组(相邻后缀的lcp长度)。