spoj 705 求不同子串的个数(后缀数组)
http://www.spoj.com/problems/SUBST1/
题意:给定一个字符串,求不相同的子串的个数。
解题思路:对于一个后缀sa[k],它产生了n-sa[k]个前缀,减去height[k]个相同的前缀(与前一个比较),则产生了n-sa[k]-height[k]个子串。累加后即结果。
View Code
1 /* 2 *Author: Zhaofa Fang 3 *Created time: 2013-04-21-21.19 4 *Language: C++ 5 */ 6 #include <cstdio> 7 #include <cstdlib> 8 #include <sstream> 9 #include <iostream> 10 #include <cmath> 11 #include <cstring> 12 #include <algorithm> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 #include <queue> 17 #include <map> 18 #include <set> 19 using namespace std; 20 21 typedef long long ll; 22 #define DEBUG(x) cout<< #x << ':' << x << endl 23 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 24 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 25 #define REP(i,n) FOR(i,0,n-1) 26 #define REPD(i,n) FORD(i,n-1,0) 27 #define PII pair<int,int> 28 #define PB push_back 29 #define MP make_pair 30 #define ft first 31 #define sd second 32 #define lowbit(x) (x&(-x)) 33 #define INF (1<<30) 34 35 const int maxn = 1111; 36 char s[maxn]; 37 int sa[maxn],t1[maxn],t2[maxn],c[maxn]; 38 int rank[maxn],height[maxn]; 39 40 void getHeight(int n){ 41 int k = 0; 42 for(int i=1;i<=n;i++)rank[sa[i]] = i; 43 for(int i=0;i<n;i++){ 44 if(k)k--; 45 int j = sa[rank[i]-1]; 46 while(s[i+k]==s[j+k])k++; 47 height[rank[i]] = k; 48 } 49 } 50 bool cmp(int *r,int a,int b,int l){ 51 return (r[a]==r[b] && r[a+l]==r[b+l]); 52 } 53 void build_sa(int m,int n){ 54 int i,*x=t1,*y=t2,k,p; 55 for( i=0;i<m;i++)c[i] = 0; 56 for( i=0;i<n;i++)c[x[i] = s[i]]++; 57 for( i=1;i<m;i++)c[i] += c[i-1]; 58 for( i=n-1;i>=0;i--)sa[-- c[x[i]]] = i; 59 for(k=1,p=0;p<n;m=p,k<<=1){ 60 p = 0; 61 for(i=n-k;i<n;i++)y[p++] = i; 62 for(i=0;i<n;i++)if(sa[i]>=k)y[p++] = sa[i]-k; 63 for(i=0;i<m;i++)c[i] = 0; 64 for(i=0;i<n;i++)c[x[y[i]]]++; 65 for(i=1;i<m;i++)c[i] += c[i-1]; 66 for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]] = y[i]; 67 swap(x,y); 68 p = 1; x[sa[0]] = 0; 69 for(i=1;i<n;i++) 70 x[sa[i]] = cmp(y,sa[i-1],sa[i],k)?p-1:p++; 71 } 72 getHeight(n-1); 73 } 74 int solve(int n){ 75 int ans = n - sa[1]; 76 for(int i=2;i<=n;i++){ 77 ans += n-sa[i]-height[i]; 78 } 79 return ans; 80 } 81 int main(){ 82 //freopen("in","r",stdin); 83 //freopen("out","w",stdout); 84 int T; 85 cin>>T; 86 while(T--){ 87 scanf("%s",s); 88 int n = strlen(s); 89 build_sa(255,n+1); 90 printf("%d\n",solve(n)); 91 } 92 return 0; 93 }
by Farmer