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.
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.
Sol:
某个子串一定是某个后缀的前缀, 那么原问题等价于求所有后缀之间的不相
同的前缀的个数。如果所有的后缀按照 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]个不同的子串。累加后便是原问题的答案。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define maxn 2005 using namespace std; char st[1001]; int ca,n,ans,tot,tmp[maxn],rankk[maxn],sa[maxn],sum[maxn],hei[maxn]; int main(){ scanf("%d",&ca); while (ca--){ scanf("%s",st+1); n=strlen(st+1); memset(sum,0,sizeof(sum)); for (int i=1;i<=n;i++) sum[tmp[i]=st[i]]++; for (int i=1;i<=256;i++) sum[i]+=sum[i-1]; for (int i=n;i>=1;i--) sa[sum[tmp[i]]--]=i; tot=0; rankk[sa[1]]=++tot; for (int i=2;i<=n;i++){ if (tmp[sa[i]]!=tmp[sa[i-1]]) tot++; rankk[sa[i]]=tot; } for (int len=1;len<=n;len<<=1){ memset(sum,0,sizeof(sum)); for (int i=1;i<=n;i++) sum[rankk[i+len]]++; for (int i=1;i<=n;i++) sum[i]+=sum[i-1]; for (int i=n;i>=1;i--) tmp[sum[rankk[i+len]]--]=i; memset(sum,0,sizeof(sum)); for (int i=1;i<=n;i++) sum[rankk[i]]++; for (int i=1;i<=n;i++) sum[i]+=sum[i-1]; for (int i=n;i>=1;i--) sa[sum[rankk[tmp[i]]]--]=tmp[i]; tot=0; tmp[sa[1]]=++tot; for (int i=2;i<=n;i++){ if (rankk[sa[i]]!=rankk[sa[i-1]]||rankk[sa[i]+len]!=rankk[sa[i-1]+len]) tot++; tmp[sa[i]]=tot; } for (int i=1;i<=n;i++) rankk[i]=tmp[i]; } hei[1]=0; for (int i=1,j=0;i<=n;i++){ if (rankk[i]==1) continue; while (st[i+j]==st[sa[rankk[i]-1]+j]) j++; hei[rankk[i]]=j; if (j) j--; } ans=n; for (int i=2;i<=n;i++){ ans+=(n-i+1); ans-=hei[i]; } printf("%d\n",ans); } return 0; }
原文地址:https://www.cnblogs.com/cutemush/p/12336866.html