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.
题意:给你一个字符串, 求有几种子串
解题思路:后缀数组
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
using namespace std;
#define N 200010
struct Sa
{
char s[N];
int rk[2][N],sa[N],h[N],w[N],now,n;
int rmq[N][20],lg[N];
bool GetS()
{
scanf("%s",s+1);
return true;
}
void getsa(int z,int &m)
{
int x=now,y=now^=1;
for(int i=1;i<=z;i++) rk[y][i]=n-i+1;
for(int i=1,j=z;i<=n;i++)
if(sa[i]>z) rk[y][++j]=sa[i]-z;
for(int i=1;i<=m;i++) w[i]=0;
for(int i=1;i<=n;i++) w[rk[x][rk[y][i]]]++;
for(int i=1;i<=m;i++) w[i]+=w[i-1];
for(int i=n;i>=1;i--) sa[w[rk[x][rk[y][i]]]--]=rk[y][i];
for(int i=m=1;i<=n;i++)
{
int *a=rk[x]+sa[i],*b=rk[x]+sa[i-1];
rk[y][sa[i]]=*a==*b&&*(a+z)==*(b+z)?m-1:m++;
}
}
void getsa(int m)
{
now=rk[1][0]=sa[0]=s[0]=0;
n=strlen(s+1);
for(int i=1;i<=m;i++) w[i]=0;
for(int i=1;i<=n;i++) w[s[i]]++;
for(int i=1;i<=m;i++) rk[1][i]=rk[1][i-1]+(bool)w[i];
for(int i=1;i<=m;i++) w[i]+=w[i-1];
for(int i=1;i<=n;i++) rk[0][i]=rk[1][s[i]];
for(int i=1;i<=n;i++) sa[w[s[i]]--]=i;
for(int x=1,y=rk[1][m];x<=n&&y<=n;x<<=1) getsa(x,y);
for(int i=1,j=0;i<=n;h[rk[now][i++]]=j?j--:j)
{
if(rk[now][i]==1) continue;
int k=n-max(sa[rk[now][i]-1],i);
while(j<=k&&s[sa[rk[now][i]-1]+j]==s[i+j]) ++j;
}
}
void getrmq()
{
h[n+1]=h[1]=lg[1]=0;
for(int i=2;i<=n;i++)
rmq[i][0]=h[i],lg[i]=lg[i>>1]+1;
for(int i=1;(1<<i)<=n;i++)
{
for(int j=2;j<=n;j++)
{
if(j+(1<<i)>n+1) break;
rmq[j][i]=min(rmq[j][i-1],rmq[j+(1<<i-1)][i-1]);
}
}
}
int lcp(int x,int y)
{
int l=min(rk[now][x],rk[now][y])+1,r=max(rk[now][x],rk[now][y]);
return min(rmq[l][lg[r-l+1]],rmq[r-(1<<lg[r-l+1])+1][lg[r-l+1]]);
}
void work()
{
GetS();getsa(300);
int ans=n-sa[1]+1;
for(int i=2;i<=n;i++)
ans+=n-sa[i]-h[i]+1;
printf("%d\n",ans);
}
}sa;
int main()
{
int t;
scanf("%d",&t);
while(t--) sa.work();
return 0;
}