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[1]), suffix(sa[2]),
suffix(sa[3]), ...... ,suffix(sa[n])的顺序计算,不难发现,对于每一次新加
进来的 后缀 suffix(sa[k]), 它将产生 n-sa[k]+1 个新 的前缀。 但是其中有
height[k]个是和前面的字符串的前缀是相同的。所以 suffix(sa[k])将“贡献”
出 n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。这个做法
的时间复杂度为 O(n)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100005;
struct SuffixArray {
char s[maxn]; // 原始字符数组(最后一个字符应必须是0,而前面的字符必须非0)
int sa[maxn]; // 后缀数组
int rank1[maxn]; // 名次数组. rank[0]一定是n-1,即最后一个字符
int height[maxn]; // height数组
int t[maxn], t2[maxn], c[maxn]; // 辅助数组
int n; // 字符个数
void clear() { n = 0; memset(sa, 0, sizeof(sa)); }
// m为最大字符值加1。调用之前需设置好s和n
void build_sa(int m) {
int i, *x = t, *y = t2;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[i] = s[i]]++;
for(i = 1; i < m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
for(int k = 1; k <= n; k <<= 1) {
int p = 0;
for(i = n-k; i < n; i++) y[p++] = i;
for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[y[i]]]++;
for(i = 0; i < m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = 1; x[sa[0]] = 0;
for(i = 1; i < n; i++)
x[sa[i]] = y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k] ? p-1 : p++;
if(p >= n) break;
m = p;
}
}
void build_height() {
int i, j, k = 0;
for(i = 0; i < n; i++) rank1[sa[i]] = i;
for(i = 0; i < n; i++) {
if(k) k--;
int j = sa[rank1[i]-1];
while(s[i+k] == s[j+k]) k++;
height[rank1[i]] = k;
}
}
};
SuffixArray sol;
int T;
int main()
{
// freopen("data.txt","r",stdin);
ios_base::sync_with_stdio(false);
cin >> T;
while(T--)
{
memset(sol.s,0,sizeof(sol.s));
cin >> sol.s;
sol.clear();
sol.n = strlen(sol.s)+1;
sol.build_sa(130);
// for(int i=0;i<sol.n;i++)
// {
// cout << sol.sa[i]<<" ";
// }
// cout <<endl;
sol.build_height();
// sol.n--;
ll ans = 0 ;
for(int i=1;i<sol.n;i++)
{
ans += sol.n - sol.sa[i]-1 - sol.height[i];
}
cout << ans<<endl;
}
return 0;
}