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 }