求不同子串的个数有多少。
子串总数是len*(len+1)/2个,每一个子串必然是某个后缀的前缀子串..相同子串所在后缀的sa肯定是相邻的,然后基本就是height数组了...
所以就是总数-height数组和..
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
#define N 2012
int sa[N],ra[N],height[N];
int t1[N],t2[N],c[N],s[N];
char a[N];
int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void getsa(int n,int m)
{
int i,j,p,*x=t1,*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(j=1;j<=n;j<<=1)
{
p=0;
for(i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<m;i++)c[i]=0;
for(i=0;i<n;i++)c[x[y[i]]]++;
for(i=1;i<m;i++)c[i]+=c[i-1];
for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
for(swap(x,y),p=1,i=1,x[sa[0]]=0; i<n; i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
if(p>=n)break;
m=p;
}
}
void getheight(int n)
{
int i,j,k=0;
for(i=1;i<=n;i++) ra[sa[i]]=i;
for(i=0;i<n;i++)
{
if(k) k--;
j=sa[ra[i]-1];
while(s[i+k]==s[j+k]) k++;
height[ra[i]]=k;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",a);
int len=strlen(a);
for(int i=0;i<=len;i++)
s[i]=a[i];
getsa(len+1,128);
getheight(len);
int ans=len*(len+1)/2;
for(int i=2;i<=len;i++)
ans-=height[i];
printf("%d\n",ans);
}
return 0;
}