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 }

 

你可能感兴趣的:(substr)