SPOJ DISUBSTR Distinct Substrings

来源:互联网 发布:网络黄金egd中国站 编辑:程序博客网 时间:2024/06/03 19:17

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.

跑完后缀数组以后,后缀sa[i]总共有n-sa[i]+1个前缀,其中有height[i]个重复,所以答案是sigma(n-sa[i]-height[i]+1)。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;char s[1010];int a[1010],sa[1010],rank[1010],height[1010],cnt[1010],ord[1010],t1[1010],t2[1010],n;int main(){    int T,i,j,k,m,p,q,*x=t1,*y=t2,ans;    scanf("%d",&T);    while (T--)    {        memset(a,0,sizeof(a));        scanf("%s",s+1);        n=strlen(s+1);        for (i=1;i<=n;i++)          ord[i]=s[i];        sort(ord+1,ord+n+1);        m=unique(ord+1,ord+n+1)-ord-1;        for (i=1;i<=n;i++)          a[i]=lower_bound(ord+1,ord+m+1,s[i])-ord;        for (i=1;i<=m;i++)          cnt[i]=0;        for (i=1;i<=n;i++)          cnt[x[i]=a[i]]++;        for (i=2;i<=m;i++)          cnt[i]+=cnt[i-1];        for (i=n;i;i--)          sa[cnt[x[i]]--]=i;        for (k=1;k<=n;k<<=1)        {            p=0;            for (i=n-k+1;i<=n;i++)              y[++p]=i;            for (i=1;i<=n;i++)              if (sa[i]-k>=1)                y[++p]=sa[i]-k;            for (i=1;i<=m;i++)              cnt[i]=0;            for (i=1;i<=n;i++)              cnt[x[y[i]]]++;            for (i=2;i<=m;i++)              cnt[i]+=cnt[i-1];            for (i=n;i;i--)              sa[cnt[x[y[i]]]--]=y[i];            swap(x,y);            p=x[sa[1]]=1;            for (i=2;i<=n;i++)            {                if (y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) p++;                x[sa[i]]=p;             }            if ((m=p)>=n) break;        }        for (i=1;i<=n;i++)          rank[sa[i]]=i;        for (i=1,k=0;i<=n;i++)        {            if (k) k--;            if (rank[i]==1)            {                k=0;                continue;            }            while (a[i+k]==a[sa[rank[i]-1]+k]) k++;            height[rank[i]]=k;        }        ans=0;        for (i=1;i<=n;i++)          ans+=n-sa[i]-height[i]+1;        printf("%d\n",ans);    }}
0 0