学习jjh同学搞个模板集合
后缀数组:
1 int n,m; char s[310000]; 2 int rank[310000]; 3 int cnt[310000],cnt_rank[310000]; 4 int rank1[310000],rank2[310000]; 5 int SA[310000],tempSA[310000];//应该是桶 6 void get_suffix_rank(){ 7 memset(cnt,0,sizeof(cnt)); 8 //以下是对单个字母排序 9 for(int i=0;i<n;i++) cnt[s[i]]++;//计数 10 for(int i=‘a‘;i<=‘z‘;i++) cnt[i]+=cnt[i-1];//把计数堆起来,这样后面搞名次直接用这个堆起来的数就行了 11 for(int i=0;i<n;i++) rank[i]=cnt[s[i]]-1;//这里搞了个‘$‘,所以要-1,让‘$‘的名次为0 12 //因为名次是堆出来的,所以这个版本a,b,a,a对应的名次是1,4,1,1(单个字符名次)(不知道其他版本是不是一。一) 13 for(int l=1;l<n;l*=2){//倍增长度 14 for(int i=0;i<n;i++){//搞出rank[1]和rank[2] 15 rank1[i]=rank[i]; 16 rank2[i]=(i+l<n) ? rank[i+l] : 0; 17 } 18 //基数排序排rank1和rank2 19 memset(cnt_rank,0,sizeof(cnt_rank)); 20 for(int i=0;i<n;i++) cnt_rank[rank2[i]]++; 21 for(int i=1;i<n;i++) cnt_rank[i]+=cnt_rank[i-1];//还是堆名次 22 for(int i=n-1;i>=0;i--) tempSA[--cnt_rank[rank2[i]]]=i;//应该是进桶 23 memset(cnt_rank,0,sizeof(cnt_rank)); 24 for(int i=0;i<n;i++) cnt_rank[rank1[i]]++; 25 for(int i=1;i<n;i++) cnt_rank[i]+=cnt_rank[i-1]; 26 for(int i=n-1;i>=0;i--) SA[--cnt_rank[rank1[tempSA[i]]]]=tempSA[i];//rank1[tempSA[i]]应该相当于出桶 27 rank[SA[0]]=0; 28 for(int i=1;i<n;i++){ 29 rank[SA[i]]=rank[SA[i-1]]; 30 if(rank1[SA[i]]!=rank1[SA[i-1]] || rank2[SA[i]]!=rank2[SA[i-1]]) rank[SA[i]]++; 31 } 32 } 33 } 34 int main(){freopen("ddd.in","r",stdin); 35 cin>>n; 36 char ch=getchar(); while(ch<‘a‘||ch>‘z‘) ch=getchar(); 37 for(int i=0;i<n;i++){ s[i]=ch; ch=getchar();} 38 s[++n]=‘$‘;//这应该是个记号,让a比a$小 39 get_suffix_rank();
时间: 2024-10-22 17:43:50