Distinct Substrings(spoj 694)

题意:要求不同子串的个数

/*
    先求出height数组,不难看出height之和就是重复的字符串个数,用总的减去它就行了。
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#define N 100010
int sa[N],rk[N],height[N],t1[N],t2[N],c[N];
char s[N];
using namespace std;
bool cmp(int *y,int a,int b,int k){
    return y[a]==y[b]&&y[a+k]==y[b+k];
}
void DA(int n,int m){
    int *x=t1,*y=t2;
    for(int i=0;i<m;i++) c[i]=0;
    for(int i=0;i<n;i++) c[x[i]=s[i]]++;
    for(int i=1;i<m;i++) c[i]+=c[i-1];
    for(int i=n-1;~i;i--) sa[--c[x[i]]]=i;
    for(int k=1,p=0;k<=n;k*=2,m=p,p=0){
        for(int i=n-k;i<n;i++) y[p++]=i;
        for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
        for(int i=0;i<m;i++) c[i]=0;
        for(int i=0;i<n;i++) c[x[y[i]]]++;
        for(int i=1;i<m;i++) c[i]+=c[i-1];
        for(int i=n-1;~i;i--) sa[--c[x[y[i]]]]=y[i];
        swap(x,y);p=1;x[sa[0]]=0;
        for(int i=1;i<n;i++)
            if(cmp(y,sa[i-1],sa[i],k)) x[sa[i]]=p-1;
            else x[sa[i]]=p++;
        if(p>=n) break;
    }
    for(int i=0;i<n;i++) rk[sa[i]]=i;
}
void get_ht(int n){
    for(int i=0,j,k=0;i<n;height[rk[i++]]=k){
        j=sa[rk[i]-1];k=k?k-1:0;
        while(s[i+k]==s[j+k]) k++;
    }
}
int solve(int n){
    long long sum=1LL*n*(n+1)/2;
    for(int i=1;i<=n;i++) sum-=(long long)height[i];
    return (int)sum;
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%s",s);int n=strlen(s);
        DA(n+1,128);
        get_ht(n);
        printf("%d\n",solve(n));
    }
    return 0;
}
时间: 2024-10-06 22:29:01

Distinct Substrings(spoj 694)的相关文章

SPOJ 694、705 Distinct Substrings 、 New Distinct Substrings (后缀数组)

题目大意: 求串中不同的子串的个数. 思路分析: 子串一定是某一个后缀的前缀. 所以我们把每一个后缀拿出来,分析它有多少个前缀,然后除去它与sa数组中前面那个后缀相同的前缀. 最后也就是 ans = segma (n-sa[i] + height[i]).... #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define maxn 1000005

【SPOJ】Distinct Substrings(后缀自动机)

[SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/endpos\)集合的大小 但是实际上我们没有任何必要减去不合法的数量 我们只需要累加每个节点表示的合法子串的数量即可 这个值等于\(longest-shortest+1=longest-parent.longest\) #include<iostream> #include<cstdio&g

spoj 694 Distinct Substrings(后缀数组)

题目:求一个字符串中所有不同子串个数 后缀数组经典题,每一个子串一定是某个后缀的前缀,那么问题便等价于求所有后缀之间的不相同的前缀个数.我们按sa的顺序来考虑,当加入sa[k]的时候,sa[k]这个后缀的长度为n-sa[k]-1,那么便有n-sa[k]-1个前缀,但是由heigh数组可知sa[k]与sa[k-1]有height[k]个前缀是相同的,所以要除去. 注意的是这道题题意有点坑,一开始以为字母只能是大写的而且长度在1000之内,可发现根本不是这样!!!!!!!!最后改了m的值又把数组开到

SPOJ 705 Distinct Substrings(后缀数组)

[题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每个后缀对答案的贡献为n-sa[i]+1-h[i], 因为排名相邻的后缀一定是公共前缀最长的, 那么就可以有效地通过LCP去除重复计算的子串. [代码] #include <cstdio> #include <cstring> #include <algorithm> usi

【SPOJ694&amp;705】Distinct Substrings(后缀数组)

题意:求一个字符串的不相同的子串个数 n<=1000 思路:这是一道论文题 1 var a,x,y,sa,rank,height,wc,wd:array[0..3000]of longint; 2 n,i,m,ans,v,cas:longint; 3 ch:ansistring; 4 5 procedure swap(var x,y:longint); 6 var t:longint; 7 begin 8 t:=x; x:=y; y:=t; 9 end; 10 11 function cmp(a

SPOJ 题目694 Distinct Substrings(后缀数组,求不同的子串个数)

DISUBSTR - Distinct Substrings no tags 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

SPOJ Distinct Substrings(后缀数组求不同子串个数,好题)

DISUBSTR - Distinct Substrings no tags 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

SPOJ - DISUBSTR Distinct Substrings (不相同的子串的个数)

Distinct Substrings  Time Limit: 159MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu 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

SPOJ 题目705 New Distinct Substrings(后缀数组,求不同的子串个数)

SUBST1 - New Distinct Substrings no tags 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 <= 50000 Output For each test case out