hdu 4622 Reincarnation(字符串Hash+线段树)

题意:给出一个字符串,最长2000,Q个询问,每次询问[L,R]区间内有多少个不同的字串。

可以用后缀自动机做,也可以先把字符串Hash成一个个整数,转化成求一个区间内不同的整数个数。用Trie树Hash超内存了。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef unsigned int uint;
struct hash_map
{
    const static int mod=2000007;

    int head[mod],nEle;

    struct node
    {
        uint key1,key2;
        int key3,pos,pre;
        node(){}
        node(uint key1,uint key2,int key3,int pos,int pre) :
            key1(key1),key2(key2),key3(key3),pos(pos),pre(pre) {}
    }ele[2000000];

    void init()
    {
        nEle=0;
        memset(head,-1,sizeof(head));
    }
    void clear()
    {
        for(int i=0;i<nEle;i++)
            head[ele[i].key1%mod]=-1;
        nEle=0;
    }
    int find(uint key1,uint key2,int len)
    {
        int hashcode=key1%mod;
        for(int i=head[hashcode];i!=-1;i=ele[i].pre)
            if(ele[i].key1==key1&&ele[i].key2==key2&&ele[i].key3==len)
                return i;
        return -1;
    }
    int getPos(uint key1,uint key2,int len)
    {
        int pos=find(key1,key2,len);
        if(pos==-1) return -1;
        return ele[pos].pos;
    }
    void updata(uint key1,uint key2,int len,int pos)
    {
        int idx=find(key1,key2,len);
        if(idx==-1)
        {
            int tmp=key1%mod;
            ele[nEle]=node(key1,key2,len,pos,head[tmp]);
            head[tmp]=nEle++;
        }
        else ele[idx].pos=pos;
    }
}hash;

    int T[2100],LIM;

    int lowbit(int x) { return x&(-x); }
    void add(int idx1,int idx2)
    {
        //cout<<idx1<<" "<<idx2<<endl;
        for(int i=idx1;i<=LIM;i+=lowbit(i)) T[i]+=1;
        for(int i=idx2+1;i<=LIM;i+=lowbit(i)) T[i]-=1;
    }
    int query(int idx)
    {
        if(idx<=0) return 0;

        int sum=0;
        for(int i=idx;i>0;i-=lowbit(i)) sum+=T[i];
        return sum;
    }

struct OP
{
    int st,ed,id;
    OP(){}
    OP(int st,int ed,int id) :
        st(st),ed(ed),id(id) {}
    bool operator<(const OP &B)const
    {
        return ed<B.ed;
    }
}op[10005];

const int MaxLen=2100;
const int mut1=127;
const int mut2=131;

int res[10005];

int main()
{

    int t;
    scanf("%d",&t);

    hash.init();

    while(t--)
    {
        char s[MaxLen];
        scanf("%s",s+1);
        int len=(int)strlen(s+1);

        hash.clear();
        LIM=len;
        for(int i=1;i<=len;i++) T[i]=0;

        int Q; scanf("%d",&Q);
        for(int i=0;i<Q;i++)
        {
            int st,ed; scanf("%d%d",&st,&ed);
            op[i]=OP(st,ed,i);
        }
        sort(op,op+Q);

        int ind=0;
        for(int i=1;i<=len;i++)
        {
            uint key1=0,key2=0;
            for(int j=i;j>=1;j--)
            {
                key1=key1*mut1+s[j];
                key2=key2*mut2+s[j];
                int pos=hash.getPos(key1,key2,i-j+1);
                if(pos==-1) pos=0;

                add(pos+1,j);
                hash.updata(key1,key2,i-j+1,j);

            }
            while(ind<Q&&op[ind].ed==i)
            {
                res[op[ind].id]=query(op[ind].st);
                ind++;
            }
        }
        for(int i=0;i<Q;i++) printf("%d\n",res[i]);
    }
    return 0;
}


你可能感兴趣的:(hdu 4622 Reincarnation(字符串Hash+线段树))