某谷的板子很水,传送门,错误的板子都能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 } }
当我发现我研究了好久的码有错误时,内心一千只草泥马奔过。。。。。。
也是第一次碰到这种事情,这个事情告诉我,不要迷信。