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.
SPOJ还有一个题是【SUBST1 - New Distinct Substrings】,一模一样,不过nlog^2n过不了。
计数问题,贡献是当前后缀生成的子串数目减去高度数组的大小,也就是重复的子串数目。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int SZ = 1000010;
int lcp[SZ],sa[SZ],tmp[SZ],k = 1,n,rank[SZ];
bool cmp_sa(int i,int j)
{
if(rank[i] != rank[j]) return rank[i] < rank[j];
else
{
int x = i + k <= n ? rank[i + k] : -1;
int y = j + k <= n ? rank[j + k] : -1;
return x < y;
}
}
void get_sa(char s[])
{
for(int i = 0;i <= n;i ++)
{
sa[i] = i;
rank[i] = i == n ? -1 : s[i];
}
for(k = 1;k <= n;k <<= 1)
{
sort(sa,sa + 1 + n,cmp_sa);
tmp[sa[0]] = 0;
for(int i = 1;i <= n;i ++)
tmp[sa[i]] = tmp[sa[i - 1]] + (cmp_sa(sa[i - 1],sa[i]) ? 1 : 0);
for(int i = 0;i <= n;i ++)
rank[i] = tmp[i];
}
}
void get_lcp(char s[])
{
int h = 0;
lcp[0] = 0;
for(int i = 0;i <= n;i ++)
rank[sa[i]] = i;
for(int i = 0;i < n;i ++)
{
int j = sa[rank[i] - 1];
// cout<<"sa:"<<i<<" "<<j<<endl;
if(h) h --;
while(i + h < n && j + h < n)
{
if(s[i + h] == s[j + h]) h ++;
else break;
}
lcp[rank[i] - 1] = h;
}
}
LL ask()
{
LL ans = 0;
for(int i = 1;i <= n;i ++)
{
ans += n - sa[i] - lcp[i];
// cout<<n - sa[i] - lcp[i]<<endl;
}
return ans;
}
void init()
{
memset(sa,0,sizeof(sa));
memset(lcp,0,sizeof(lcp));
memset(rank,0,sizeof(rank));
memset(tmp,0,sizeof(tmp));
}
char s[SZ];
int main()
{
int T;
scanf("%d",&T);
while(T --)
{
init();
scanf("%s",s);
n = strlen(s);
get_sa(s);
get_lcp(s);
/* for(int i = 0;i <= n;i ++)
printf("%d ",lcp[i]); puts("");
for(int i = 0;i <= n;i ++)
printf("%d ",sa[i]); puts("");*/
printf("%lld\n",ask());
}
return 0;
}
/*
2
CCCCC
ABABA
*/