白书后缀数组模板纠错

某谷的板子很水,传送门,错误的板子都能ac。

建议去uoj练习这个板子,传送门,还可以顺便练习lcp。

可以去看noi集训队2009论文 罗穗骞《后缀数组——处理字符串的有力工具》,这个网上有很多资源就不贴传送门了。

char s[MAXN];
int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],n;
void build_sa(int m){
    int i,*x=t,*y=t2;

    for(i=0;i<m;i++) c[i]=0;
    for(i=0;i<n;i++) c[x[i]=s[i]]++;
    for(i=1;i<m;i++) c[i]+=c[i-1];
    for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    for(int k=1;k<=n;k<<=1){
        int p=0;
        for(i=n-k;i<n;i++) y[p++]=i;
        for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
        
        for(i=0;i<m;i++) c[i]=0;
        for(i=0;i<n;i++) c[x[y[i]]]++;
        for(i=0;i<m;i++) c[i]+=c[i-1];//错误1
        //应该是想写for(i=0;i<m;i++) c[i]+=c[i-1];
        //很明显从0开始会访问到c[-1]导致段错误
        for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            s[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;//错误2&3
        //这里有两个坑 第一个坑是y[sa[i]+k]会越界 所以数组得开双倍
        //第二个坑是可能y[sa[i-1]+k]和y[sa[i]+k]一个越界了但是一个没有越界 越界的值必然是0但是没有越界的也可能是0 这种情况就会出现错误
        //比如一连串相同的字符 aaaaaaaa 白书的代码肯定过不了
        //我的改法是索性直接从1开始
        //这里把sa数组预处理为-1应该也可以过
        if(p>=n) break;
        m=p;
    }
}
int rank[MAXN],height[MAXN];
void getHeight(){
    int i,j,k=0;
    for(i=0;i<n;i++) rank[sa[i]]=i;
    for(i=0;i<n;i++){
        if(k)k--;
        int j=sa[rank[i]-1];//错误4
        //很明显的越界,会导致段错误,我的处理方法是特判。
        //加一句
        /*
        if(rank[i]==0){rank[i]=k=0;continue;}
        */
        while(s[i+k]==s[j+k]) k++;
        height[rank[i]]=k
    }
}

 当我发现我研究了好久的码有错误时,内心一千只草泥马奔过。。。。。。

也是第一次碰到这种事情,这个事情告诉我,不要迷信。

猜你喜欢

转载自www.cnblogs.com/tmzengbi/p/12127867.html