标签:
个人感觉后缀数组的板子太难背了,听了小火车讲二分+哈希可以实现求后缀数组,貌似很好理解,代码如下。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 using namespace std; 10 typedef long long LL; 11 typedef unsigned long long ULL; 12 const int maxn=200000; 13 const ULL BASE=127; 14 char s[maxn]; 15 int sa[maxn],rank[maxn]; 16 ULL a[maxn],base[maxn],hash[maxn],len; 17 struct H{ 18 int pos; 19 }suf[maxn]; 20 inline ULL get_hash(int l,int r){ 21 return hash[r]-hash[l-1]*base[r-l+1]; 22 } 23 inline int find(int l,int r,int f1,int f2){ 24 if(l+1>=r){ 25 if(get_hash(f1,f1+r-1)==get_hash(f2,f2+r-1)) return r; 26 else return l; 27 } 28 int mid=(l+r)>>1; 29 if(get_hash(f1,f1+mid-1)==get_hash(f2,f2+mid-1)) return find(mid,r,f1,f2); 30 else return find(l,mid-1,f1,f2); 31 } 32 inline bool cmp(const H &x,const H &y){ 33 int len1=len-x.pos+1,len2=len-y.pos+1; 34 int maxx=find(0,min(len1,len2)+1,x.pos,y.pos); 35 if(maxx==min(len1,len2)+1) return len1<len2; 36 else return a[x.pos+maxx]<a[y.pos+maxx]; 37 } 38 int height[maxn]; 39 inline void calheight(){ 40 int k=0; 41 for(int i=1;i<=len;i++){ 42 if(k!=0) k--; 43 for(int j=sa[rank[i]-1];;k++){ 44 if(a[i+k]!=a[j+k]) break; 45 } 46 height[rank[i]]=k; 47 } 48 return ; 49 } 50 int main(){ 51 scanf("%s",s+1); len=strlen(s+1); 52 for(int i=1;i<=len;i++) a[i]=ULL(s[i]-‘a‘+1); 53 base[0]=1; for(int i=1;i<=len;i++) base[i]=base[i-1]*BASE; 54 for(int i=1;i<=len;i++) hash[i]=hash[i-1]*BASE+a[i]; 55 for(int i=1;i<=len;i++){ 56 suf[i].pos=i; 57 } 58 sort(suf+1,suf+len+1,cmp); 59 for(int i=1;i<=len;i++){ 60 sa[i]=suf[i].pos; rank[suf[i].pos]=i; 61 } 62 calheight(); 63 for(int i=1;i<=len;i++){ 64 cout<<height[i]<<" "; 65 } 66 return 0; 67 }
标签:
原文地址:http://www.cnblogs.com/CXCXCXC/p/5380755.html