DISUBSTR - Distinct Substrings
Description
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.
题目大意
给定一个字符串,求不相同的子串的个数。
题解
论文中例5,比较简单的一道模板题。
考虑每个子串对应一个后缀的前缀,题目就是求所有后缀不相同的前缀的个数。按照sa的顺序计算每个后缀,那么第sa[i]个后缀对答案的贡献就是
n−sa[i]+1−height[i]
。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1000 + 10;
char s[N];
int t, n, a[N];
int v[N], sa[2][N], rk[2][N], ht[N], p, q, k, ans;
void init(){
scanf("%s", s+1);
n = strlen(s+1);
for(int i = 1; i <= n; i++) a[i] = (int) s[i];
memset(sa, 0, sizeof(sa));
memset(rk, 0, sizeof(rk));
memset(ht, 0, sizeof(ht));
memset(v, 0, sizeof(v));
ans = 0;
}
void calsa(int *sa1, int *rk1, int *sa2, int *rk2){
for(int i = 1; i <= n; i++) v[rk1[sa1[i]]] = i;
for(int i = n; i >= 1; i--) if(sa1[i] > k) sa2[v[rk1[sa1[i]-k]]--] = sa1[i] - k;
for(int i = n-k+1; i <= n; i++) sa2[v[rk1[i]]--] = i;
for(int i = 1; i <= n; i++)
rk2[sa2[i]] = rk2[sa2[i-1]] + (rk1[sa2[i-1]] != rk1[sa2[i]] || rk1[sa2[i-1]+k] != rk1[sa2[i]+k]);
}
void calheight(){
int k = 0;
for(int i = 1; i <= n; i++){
if(k) k--;
int j = sa[p][rk[p][i]-1];
while(a[i+k] == a[j+k]) k++;
ht[rk[p][i]] = k;
}
}
void work(){
scanf("%d", &t);
while(t--){
init();
p = 0, q = 1;
for(int i = 1; i <= n; i++) v[a[i]]++;
for(int i = 1; i <= 128; i++) v[i] += v[i-1];
for(int i = 1; i <= n; i++) sa[p][v[a[i]]--] = i;
for(int i = 1; i <= n; i++)
rk[p][sa[p][i]] = rk[p][sa[p][i-1]] + (a[sa[p][i]] != a[sa[p][i-1]]);
memset(v, 0, sizeof(v));
k = 1;
while(k < n){
calsa(sa[p], rk[p], sa[q], rk[q]);
p ^= 1, q ^= 1, k <<= 1;
}
calheight();
for(int i = 1; i <= n; i++)
ans += n - sa[p][i] + 1 - ht[i];
printf("%d\n", ans);
}
}
int main(){
work();
return 0;
}