1. 程式人生 > >Distinct Substrings (spoj694)(後綴數組)

Distinct Substrings (spoj694)(後綴數組)

clr define distinct size n) nbsp strong style col

核心:每一個後綴的每一個前綴都是一個子串

相鄰後綴的lcp的值是就是重復子串的個數

用所有的子串減去sigma(height)就行了

 1 #include"bits/stdc++.h"
 2 using namespace std;
 3 #define clr(x) memset(x,0,sizeof(x))
 4 
 5 int T;
 6 char a[2000];
 7 int n,m;
 8 int x[2000],y[2000],c[2000];
 9 int sa[2000];
10 int rk[2000];
11 int ht[2000];
12 
13 inline void SA()
14 {
15    //cout<<"%^("<<endl;
16 17 // cout<<n<<" "<<m<<endl; 18 //cout<<a+1<<endl; 19 /* memset(c,0,sizeof c); 20 memset(x,0,sizeof x); 21 memset(y,0,sizeof y);*/ 22 clr(c); 23 clr(x); 24 clr(y); 25 26 27 for (int i=1;i<=n;i++) ++c[x[i] = a[i]-A]; 28 for (int i=1
;i<=m;i++) c[i]+=c[i-1]; 29 for (int i=n;i;i--) sa[c[x[i]]--] = i; 30 31 for (int k=1;k<=n;k*=2) 32 { 33 34 int num = 0; 35 for (int i=n-k+1;i<=n;i++) y[++num] = i; 36 for (int i=1;i<=n;i++) if (sa[i]>k) y[++num] = sa[i]-k; 37 memset(c,0,sizeof c); 38 for
(int i=1;i<=n;i++) ++c[x[y[i]]]; 39 for (int i=1;i<=m;i++) c[i]+=c[i-1]; 40 for (int i=n;i;i--) sa[c[x[y[i]]]--] = y[i],y[i]=0; 41 num=1; 42 swap(x,y); 43 x[sa[1]]=1; 44 45 for (int i=2;i<=n;i++) 46 { 47 x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num; 48 } 49 50 if (num==n) break; 51 m=num; 52 53 54 } 55 56 for (int i=1;i<=n;i++) rk[sa[i]] = i; 57 int k = 0; 58 59 for (int i=1;i<=n;i++) 60 { 61 if (rk[i]==1) continue; 62 if (k) k--; 63 int j =sa[rk[i]-1]; 64 65 66 while (a[i+k]==a[j+k]&&i+k<=n&&j+k<=n) k++; 67 68 ht[rk[i]] = k; 69 } 70 71 // 72 // for (int i=1;i<=n;i++ ) cout<<ht[i]<<" ";cout<<endl; 73 // / / for (int i=1;i<=n;i++) cout<<sa[i]<<" ";cout<<endl; 74 75 76 } 77 78 79 80 int main() 81 { 82 cin>>T; 83 while (T--) 84 { 85 86 m=233; 87 cin>>a+1; 88 n = strlen(a+1); 89 SA(); 90 91 int ans = n*(n+1)/2; 92 for (int i=1;i<=n;i++ ) ans -= ht[i]; 93 cout<<ans<<endl; 94 95 96 97 }

Distinct Substrings (spoj694)(後綴數組)