Distinct Substrings - spoj 694(不重复子串个数)

题目大意:RT

分析:练手题目....后缀数组确实很强大.....多理解height数组, 切勿使用模版,后缀数组本身就有很多细节,多犯错更有利理解这个算法。

代码如下:

=====================================================================================================================

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 1007;

struct SuffixArr
{
    int tempx[MAXN], tempy[MAXN], text[MAXN];
    int rank[MAXN], sa[MAXN], sum[MAXN], height[MAXN];
    int *x, *y, N, MaxId;

    void GetText(char s[])
    {
        N = strlen(s)+1;
        x = tempx, y = tempy, MaxId=300;

        for(int i=0; i<N; i++)
        {
            text[i] = x[i] = (int)s[i];
            y[i] = i;
        }
    }
    bool cmp(int i, int len)
    {
        if(sa[i]+len>N || sa[i-1]+len>N)
            return false;
        if(y[sa[i]] != y[sa[i-1]] || y[sa[i]+len] != y[sa[i-1]+len])
            return false;

        return true;
    }
    void BaseSort()
    {
        for(int i=0; i<MaxId; i++)
            sum[i] = 0;
        for(int i=0; i<N; i++)
            sum[ x[ y[i] ] ] += 1;
        for(int i=1; i<MaxId; i++)
            sum[i] += sum[i-1];
        for(int i=N-1; i>=0; i--)
            sa[ --sum[ x[ y[i] ] ] ] = y[i];
    }
    void GetSa()
    {
        BaseSort();

        for(int len=1; len<=N; len<<=1)
        {
            int id = 0;

            for(int i=N-len; i<N; i++)
                y[id++] = i;
            for(int i=0; i<N; i++)if(sa[i] >= len)
                y[id++] = sa[i]-len;

            BaseSort();
            swap(x, y);
            x[ sa[0] ] = id = 0;

            for(int i=1; i<N; i++)
            {
                if(cmp(i, len) == true)
                    x[sa[i]] = id;
                else
                    x[sa[i]] = ++id;
            }

            MaxId = id+1;

            if(MaxId >= N)break;
        }
    }
    void GetHeight()
    {
        for(int i=0; i<N; i++)
            rank[sa[i]] = i;

        for(int k=0, i=0; i<N; i++)
        {
            if(!rank[i])
            {
                height[0] = k = 0;
                continue;
            }
            if(k)k--;

            int pre = sa[ rank[i]-1 ];

            while(text[i+k] == text[pre+k])
                k++;
            height[rank[i]] = k;
        }
    }
    int TotalSonArr()
    {
        int sum = 0;

        for(int i=0; i<N; i++)
            sum += N-sa[i]-1-height[i];

        return sum;
    }
    void debug(int p[])
    {
        for(int i=0; i<N; i++)
            printf("%d ", p[i]);
        printf("\n");
    }
};

SuffixArr suf;
char s[MAXN];

int main()
{
    int T;

    scanf("%d", &T);

    while(T--)
    {
        scanf("%s", s);

        suf.GetText(s);
        suf.GetSa();
        suf.GetHeight();
        int ans = suf.TotalSonArr();

        printf("%d\n", ans);
    }

    return 0;
}
时间: 2024-12-24 22:24:24

Distinct Substrings - spoj 694(不重复子串个数)的相关文章

Spoj-DISUBSTR - Distinct Substrings~New Distinct Substrings SPOJ - SUBST1~(后缀数组求解子串个数)

Spoj-DISUBSTR - Distinct Substrings New Distinct Substrings SPOJ - SUBST1 我是根据kuangbin的后缀数组专题来的 这两题题意一样求解字符串中不同字串的个数: 这个属于后缀数组最基本的应用 给定一个字符串,求不相同的子串的个数. 算法分析: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数. 如果所有的后缀按照 suffix(sa[1]), suffix(sa[2]), suffix(sa

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

Distinct Substrings SPOJ - DISUBSTR(后缀数组水题)

求不重复的子串个数 用所有的减去height就好了 推出来的... #include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <cctype> #include <set> #include <vector> #include <stack> #include

【后缀自动机】SPOJ 8222-最多重复子串

题意: 一个长度不超过250000的字符串,求出它长度为i的子串最多出现了多少次. 后缀自动机练习题...虽说是用Cube评测的不过时限仍然鬼畜. 考虑SAM的性质: 一个串的SAM肯定可以接受这个串的所有子串.SAM上的每一个点代表了一个子串. 主链:SAM上最长的那条链,也就是说从根走到主链的尾端就是整个字符串. 用t[i]记录i号点表示的子串的出现次数,沿着主链走一遍,很明显,主链上所有的点都代表了一个前缀,每个前缀都出现过.因此主链上的点的t初始值为1. 接着,之前提到过,一个点的pre

SPOJ694--- DISUBSTR - Distinct Substrings(后缀数组)

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 distin

Spoj 694 Distinct Substrings

Given a string, we need to find the total number of its distinct substrings. 给你一个字符中,统计有多少个不同的子串InputT- number of test cases. T<=20;Each test case consists of one string, whose length is <= 1000OutputFor each test case output one number saying the n

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 题目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