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 }

 

你可能感兴趣的:(后缀数组)