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

 

posted on 2015-03-10 19:27  lienus  阅读(162)  评论(0编辑  收藏  举报

导航