spoj694 DISUBSTR

来源:互联网 发布:天地知我心二 编辑:程序博客网 时间:2024/05/21 12:40

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]个后缀对答案的贡献就是nsa[i]+1height[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;}
0 0
原创粉丝点击