SPOJ - SUBST1 New Distinct Substrings

题面在这里

题意:

给一个字符串,统计字符串中不重复的子串个数。

做法:

后缀数组模板题。
观察到每一个子串都是一个后缀的前缀,重复的前缀就是sigma(h[i]),第i小的和第i-1小的后缀的lcp。
于是我们把ans减去sigma(h[i])就好了。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cctype>
using namespace std;
typedef long long LL;

const int N = 50010;
int n, m;
char a[N];
int rk[N], tp[N], SA[N], tong[N], h[N];

inline void js_sort()
{
    for(int i = 0; i <= m; i ++) tong[i] = 0;
    for(int i = 1; i <= n; i ++) tong[rk[tp[i]]] ++;
    for(int i = 1; i <= m; i ++) tong[i] += tong[i-1];
    for(int i = n; i >= 1; i --) SA[tong[rk[tp[i]]] --] = tp[i];
}
int main()
{
    int Test; scanf("%d", &Test);
    while(Test --) {
        scanf("%s", a+1); n = strlen(a+1);
        for(int i = 1; i <= n; i ++) { rk[i] = a[i]; tp[i] = i; }
        m = 127; int p = 1, w = 1; js_sort();
        while(p < n) {
            p = 0;
            for(int i = n-w+1; i <= n; i ++) tp[++ p] = i;
            for(int i = 1; i <= n; i ++) if(SA[i] > w) tp[++ p] = SA[i]-w;
            js_sort(); swap(rk, tp); rk[SA[1]] = p = 1;
            for(int i = 2; i <= n; i ++) rk[SA[i]] = (tp[SA[i]] == tp[SA[i-1]] && tp[SA[i]+w] == tp[SA[i-1]+w]) ? p : ++ p;
            w <<= 1; m = p;
        }
        int k = 0;
        for(int i = 1; i <= n; i ++) {
            if(k > 0) k --; int j = SA[rk[i]-1];
            for(; a[i+k] == a[j+k]; k ++);
            h[rk[i]] = k;
        }
        LL ans = 1LL*n*(n+1)/2;
        for(int i = 1; i <= n; i ++) ans -= h[i];
        printf("%lld\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值