SPOJ DISUBSTR(字符串hash)

 

传送门:DISUBSTR

题意:给定一个字符串,求不同子串个数。

分析:由于数据较小,直接枚举长度为1,2...n的所有子串进行hash即可,复杂度(O(n^2)),后缀数组才是正解(O(nlogn)。

#include <iostream>

#include <algorithm>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <vector>

#include <cstdlib>

#include <map>

#define LL long long

#define N 1000010

using namespace std;

const int HASH=10007;

const int MAXN=1010;

struct HASHMAP

{

    int head[HASH],next[MAXN],size;

    unsigned long long state[MAXN];

    int f[MAXN];

    void init()

    {

        size=0;

        memset(head,-1,sizeof(head));

    }

    int insert(unsigned long long val)

    {

        int h=val%HASH;

        for(int i=head[h];~i;i=next[i])

        {

            if(val==state[i])

            {

                return 0;

            }

        }

        state[size]=val;

        next[size]=head[h];

        head[h]=size++;

        return 1;

    }

}H;

const int SEED=13331;

unsigned long long p[MAXN];

unsigned long long s[MAXN];

char str[MAXN];

int main()

{

    p[0]=1;

    for(int i=1;i<MAXN;i++)p[i]=p[i-1]*SEED;

    int T;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%s",str);

        int n=strlen(str);

        s[0]=0;

        for(int i=1;i<=n;i++)

        {

            s[i]=s[i-1]*SEED+str[i-1];

        }

        int ans=0;

        for(int L=1;L<=n;L++)

        {

            H.init();

            for(int i=1;i+L-1<=n;i++)

            {

                int res=H.insert(s[i+L-1]-s[i-1]*p[L]);

                ans+=res;

            }

        }

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

    }

}
View Code

 

你可能感兴趣的:(substr)