SPOJ 694 Distinct Substrings

Distinct Substrings

Time Limit: 1000ms
Memory Limit: 262144KB
This problem will be judged on  SPOJ. Original ID: DISUBSTR
64-bit integer IO format: %lld      Java class name: Main
 

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.

解题:求不同子串的个数,n - sa[i] - 1表示当前后缀的前缀个数,然后减去 height[i],也就是减去与前面的重复的。

SPOJ 694 Distinct Substrings
 1 #include <bits/stdc++.h>

 2 using namespace std;

 3 const int maxn = 100010;

 4 int sa[maxn],rk[maxn],height[maxn];

 5 int c[maxn],t[maxn],t2[maxn],n;

 6 char s[maxn];

 7 void build_sa(int m) {

 8     int i,j,*x = t,*y = t2;

 9     for(i = 0; i < m; ++i) c[i] = 0;

10     for(i = 0; i < n; ++i) c[x[i] = s[i]]++;

11     for(i = 1; i < m; ++i) c[i] += c[i-1];

12     for(i = n-1; i >= 0; --i) sa[--c[x[i]]] = i;

13 

14     for(int k = 1; k <= n; k <<= 1) {

15         int p = 0;

16         for(i = n-k; i < n; ++i) y[p++] = i;

17         for(i = 0; i < n; ++i)

18             if(sa[i] >= k) y[p++] = sa[i] - k;

19         for(i = 0; i < m; ++i) c[i] = 0;

20         for(i = 0; i < n; ++i) c[x[y[i]]]++;

21         for(i = 1; i < m; ++i) c[i] += c[i-1];

22         for(i = n-1; i >= 0; --i)

23             sa[--c[x[y[i]]]] = y[i];

24         swap(x,y);

25         x[sa[0]] = 0;

26         p = 1;

27         for(i = 1; i < n; ++i)

28             if(y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k])

29                 x[sa[i]] = p-1;

30             else x[sa[i]] = p++;

31         if(p >= n) break;

32         m = p;

33     }

34 }

35 void getHeight(){

36     int i,j,k = 0;

37     for(i = 0; i < n; ++i) rk[sa[i]] = i;

38     for(i = 0; i < n; ++i){

39         if(k) --k;

40         j = sa[rk[i]-1];

41         while(i+k<n&&j+k<n&&s[i+k]==s[j+k]) ++k;

42         height[rk[i]] = k;

43     }

44 }

45 int main() {

46     int kase;

47     scanf("%d",&kase);

48     while(kase--){

49         scanf("%s",s);

50         n = strlen(s) + 1;

51         build_sa(128);

52         getHeight();

53         int ret = 0;

54         for(int i = 1; i < n; ++i)

55             ret += n - sa[i] - height[i] - 1;

56         printf("%d\n",ret);

57     }

58     return 0;

59 }
View Code

 

你可能感兴趣的:(substring)