模板 后缀数组
(要点写注释里了)代码:求SA
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 int has[2000000];//桶,用于基数排序,ASCII字符集0~127 5 int sa[2000000];//后缀数组,意为排名为i的后缀起始位置 6 int tmr[2000000];//temp_rank为构建rank的临时数组后期需要去重 7 int rank[2000000];//排名,与sa互为逆映射,为以i起始的后缀的排名 8 char str[2000000]; 9 int len,cnt; 10 bool Ssame(int a,int b,int l)//去重函数,意为判断以a,b开始长度为l的子串是否相同 11 { 12 if(a+l>len||b+l>len) 13 return false;//若有一个末尾超过总长,一定可以判定两串不相同 14 return (rank[a]==rank[b])&&(rank[a+l]==rank[b+l]);//两串排名均相同则相同 15 } 16 int main() 17 { 18 scanf("%s",str+1); 19 len=strlen(str+1); 20 for(int i=1;i<=len;i++) 21 has[str[i]]++;//构建桶 22 for(int i=0;i<128;i++) 23 if(has[i]) 24 tmr[i]=++cnt;//tmr在第一次构建的时候意为字符所在排名 25 for(int i=1;i<128;i++) 26 has[i]+=has[i-1];//基数排序参数 27 for(int i=1;i<=len;i++) 28 { 29 rank[i]=str[i]; 30 sa[has[str[i]]--]=i; 31 } 32 /*第一次从文本串转化为rank数组,其实是无需离散化的*/ 33 for(int k=1;cnt!=len;k*=2) 34 { 35 cnt=0; 36 for(int i=0;i<=len;i++) 37 has[i]=0;//清空 38 for(int i=1;i<=len;i++) 39 has[rank[i]]++;//本质是rank的排序 40 for(int i=1;i<=len;i++) 41 has[i]+=has[i-1];//构建桶 42 for(int i=len;i;i--)//顺序 43 if(sa[i]>k) 44 tmr[sa[i]-k]=has[rank[sa[i]-k]]--;//有前半部分 45 for(int i=1;i<=k;i++) 46 tmr[len-i+1]=has[rank[len-i+1]]--; 47 for(int i=1;i<=len;i++) 48 sa[tmr[i]]=i; 49 for(int i=1;i<=len;i++) 50 if(Ssame(sa[i],sa[i-1],k)) 51 tmr[sa[i]]=cnt; 52 else 53 tmr[sa[i]]=++cnt; 54 for(int i=1;i<=len;i++) 55 rank[i]=tmr[i]; 56 } 57 for(int i=1;i<=len;i++) 58 printf("%d ",sa[i]); 59 puts(""); 60 return 0; 61 }
查询height:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using std::max; 5 const int N=200000; 6 int tmr[N]; 7 int rnk[N]; 8 int sa[N]; 9 int has[N]; 10 int hgt[N]; 11 char str[N]; 12 int len; 13 int cnt; 14 bool Same(int a,int b,int l) 15 { 16 if(a+l>len||b+l>len) 17 return false; 18 return (rnk[a]==rnk[b])&&(rnk[a+l]==rnk[b+l]); 19 } 20 int main() 21 { 22 scanf("%s",str+1); 23 len=strlen(str+1); 24 for(int i=1;i<=len;i++) 25 has[str[i]]++; 26 for(int i=0;i<128;i++) 27 if(has[i]) 28 tmr[i]=++cnt; 29 for(int i=1;i<128;i++) 30 has[i]+=has[i-1]; 31 for(int i=1;i<=len;i++) 32 { 33 rnk[i]=tmr[str[i]]; 34 sa[has[str[i]]--]=i; 35 } 36 for(int k=1;cnt!=len;k<<=1) 37 { 38 cnt=0; 39 for(int i=0;i<=len;i++) 40 has[i]=0; 41 for(int i=1;i<=len;i++) 42 has[rnk[i]]++; 43 for(int i=1;i<=len;i++) 44 has[i]+=has[i-1]; 45 for(int i=len;i;i--) 46 if(sa[i]>k) 47 tmr[sa[i]-k]=has[rnk[sa[i]-k]]--; 48 for(int i=1;i<=k;i++) 49 tmr[len-i+1]=has[rnk[len-i+1]]--; 50 for(int i=1;i<=len;i++) 51 sa[tmr[i]]=i; 52 for(int i=1;i<=len;i++) 53 if(Same(sa[i],sa[i-1],k)) 54 tmr[sa[i]]=cnt; 55 else 56 tmr[sa[i]]=++cnt; 57 for(int i=1;i<=len;i++) 58 rnk[i]=tmr[i]; 59 } 60 for(int i=1;i<=len;i++) 61 { 62 if(rnk[i]==1) 63 continue; 64 int j=max(1,hgt[rnk[i-1]]-1); 65 while(str[i+j-1]==str[sa[rnk[i]-1]+j-1]) 66 hgt[rnk[i]]=j++; 67 } 68 for(int i=1;i<=len;i++) 69 printf("%d ",sa[i]); 70 puts(""); 71 for(int i=2;i<=len;i++) 72 printf("%d ",hgt[i]); 73 puts(""); 74 return 0; 75 }