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 }

 

posted @ 2013-04-21 21:59  發_  阅读(1122)  评论(0编辑  收藏  举报