SPOJ 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.

Example

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.

题意:求不重复的子串有多少个
思路 : 对于一个以第k个字符为起始位置的字符串 ,他能产生的前缀为len - k 个,但是有height[rank[k]] 个是重复的,所以要减去。这道题我使用DC3 写的,

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>

using namespace std;
#define MAXN 1010*3
#define F(x) ((x)/3 + ((x)%3 == 1 ? 0 : tb))
#define G(x) ((x) < tb?(x)*3 + 1:((x) - tb)*3+2)
int wa[MAXN], wb[MAXN], wv[MAXN], wss[MAXN];
int c0(int *r, int a, int b)
{
    return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2];
}
int c12(int k, int *r, int a, int b)
{
    if(k == 2)
        return r[a] < r[b] || (r[a] == r[b] && c12(1, r, a + 1, b + 1));
      else return r[a] < r[b] || (r[a] == r[b] && wv[a + 1] < wv[b + 1]);
}
void _sort(int *r, int *a, int *b, int n, int m)
{
    int i;
    for( i = 0; i < n; i++) wv[i] = r[a[i]];
    for( i = 0; i < m; i++) wss[i] = 0;
    for( i = 0; i < n; i++) wss[wv[i]]++;
    for( i = 1; i < m; i++) wss[i] += wss[i - 1];
    for( i = n - 1; i >= 0; i--) b[--wss[wv[i]]] = a[i];
}
void dc3(int *r, int *sa, int n, int m)
{
    int i, j, *rn = r + n;
    int *san = sa + n, ta = 0, tb = (n + 1)/3, tbc = 0, p;
    r[n] = r[n+1] = 0;
    for( i = 0; i < n; i++) if(i%3 != 0) wa[tbc++] = i;
    _sort(r + 2, wa, wb, tbc, m);
    _sort(r + 1, wb, wa, tbc, m);
    _sort(r, wa, wb, tbc, m);
    for( p = 1, rn[F(wb[0])] = 0, i = 1; i < tbc; i++)
     rn[F(wb[i])] = c0(r, wb[i - 1], wb[i])? p - 1 : p ++;
    if(p < tbc) dc3(rn, san, tbc, p);
    else for( i = 0; i < tbc; i++) san[rn[i]] = i;
    for( i = 0; i < tbc; i++)
        if(san[i] < tb) wb[ta++] = san[i] * 3;
    if(n % 3 == 1) wb[ta++] = n - 1;
    _sort(r, wb, wa, ta, m);
    for( i = 0; i < tbc; i++) wv[wb[i] = G(san[i])] = i;
    for( i = 0, j = 0, p = 0; i < ta && j < tbc; p ++)
        sa[p] = c12(wb[j]%3, r, wa[i], wb[j]) ? wa[i++]: wb[j++];
    for( ; i < ta; p++) sa[p] = wa[i++];
    for( ; j < tbc; p++) sa[p] = wb[j ++];
}

void da(int str[], int sa[], int _rank[], int height[], int n, int m)
{
    for( int i = n; i < n*3; i++)
        str[i] = 0;
    dc3(str, sa, n + 1, m);
    int i, j, k = 0;
    for( i = 0; i <= n; i++) _rank[sa[i]] = i;
    for( i = 0; i < n; i++)
    {
        if(k) k --;
        j = sa[_rank[i] - 1];
        while(str[i+k] == str[j+k]) k++;
        height[_rank[i]] = k;
    }
}
char s[MAXN];
int str[MAXN], sa[MAXN], _rank[MAXN], height[MAXN];
int n, m;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",&s);
        int len =strlen(s);
        for( int i = 0; i < len; i++)
          str[i] = s[i];
        da(str, sa, _rank, height, len, 128);

        int ans = 0;

        for( int i = 1; i <= len; i++)
            ans += len - sa[i] - height[i];
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值