模板 后缀数组
Posted blog-dr-j
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板 后缀数组相关的知识,希望对你有一定的参考价值。
(要点写注释里了)代码:求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 }
以上是关于模板 后缀数组的主要内容,如果未能解决你的问题,请参考以下文章