SPOJ694 -- DISUBSTR 后缀树组求不相同的子串的个数

DISUBSTR - Distinct Substrings

 

 

Given a string, we need to find the total number of its distinct substrings.

Input

T- number of test cases. T<=20;
Each test case consists of one string, whose length is <= 1000

Output

For each test case output one number saying the number of distinct substrings.

Example

Sample Input:
2
CCCCC
ABABA

Sample Output:
5
9

Explanation for the testcase with string ABABA: 
len=1 : A,B
len=2 : AB,BA
len=3 : ABA,BAB
len=4 : ABAB,BABA
len=5 : ABABA
Thus, total number of distinct substrings is 9.

 

题意:求不同的子串的个数。

首先要知道,任意子串必是某一后缀的前缀。对于suffix[sa[i]],  它有len-sa[i]个前缀,,其中lcp[i]个子串与suffix[sa[i-1]]的前缀重复。。

每次只需要加上 len-sa[i]-lcp[i]就行了。。  

 1 #include <set>
 2 #include <map>
 3 #include <cmath>
 4 #include <ctime>
 5 #include <queue>
 6 #include <stack>
 7 #include <cstdio>
 8 #include <string>
 9 #include <vector>
10 #include <cstdlib>
11 #include <cstring>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 typedef unsigned long long ull;
16 typedef long long ll;
17 const int inf = 0x3f3f3f3f;
18 const double eps = 1e-8;
19 const int maxn = 2e4+10;
20 int sa[maxn], k, len, tmp[maxn], rank[maxn];
21 string s;
22 bool cmp(int i, int j)
23 {
24     if (rank[i] != rank[j])
25         return rank[i] < rank[j];
26     else
27     {
28         int x = (i+k <= len ? rank[i+k] : -1);
29         int y = (j+k <= len ? rank[j+k] : -1);
30         return x < y;
31     }
32 }
33 void build_sa()
34 {
35     for (int i = 0; i <= len; i++)
36     {
37         sa[i] = i;
38         rank[i] = (i < len ? s[i] : -1);
39     }
40     for (k = 1; k <= len; k *= 2)
41     {
42         sort (sa,sa+len+1,cmp);
43         tmp[sa[0]] = 0;
44         for (int i = 1; i <= len; i++)
45         {
46             tmp[sa[i]] = tmp[sa[i-1]] + (cmp(sa[i-1],sa[i])? 1 : 0);
47         }
48         for (int i = 0; i <= len; i++)
49             rank[i] = tmp[i];
50     }
51 }
52 int lcp[maxn];
53 void get_lcp()
54 {
55     for (int i = 0; i < len; i++)
56         rank[sa[i]] = i;
57     int h = 0;
58     lcp[0] = 0;
59     for (int i = 0; i < len; i++)
60     {
61         int j = sa[rank[i]-1];
62         if (h > 0)
63             h--;
64         for (; h+i < len && h+j < len; h++)
65             if (s[i+h] != s[j+h])
66                 break;
67         lcp[rank[i]] = h;
68     }
69 }
70 int main()
71 {
72     #ifndef ONLINE_JUDGE
73         freopen("in.txt","r",stdin);
74     #endif
75     int T;
76     scanf ("%d", &T);
77     while (T--)
78     {
79         cin >> s;
80         len = s.size();
81         build_sa();
82         get_lcp();
83         int ans = 0;
84         for (int i = 0; i <= len; i++)
85         {
86             ans += len - sa[i] - lcp[i];
87         }
88         printf ("%d\n",ans);
89     }
90     return 0;
91 }

 

posted @ 2015-03-18 16:14  PlasticSpirit  阅读(288)  评论(0编辑  收藏  举报