BZOJ2081: [Poi2010]Beads 哈希

来源:互联网 发布:网络实验室实施方案 编辑:程序博客网 时间:2024/06/06 23:59

题目大意:给出一个串,求按每几个一组的分割方式可以得到最多的不同子串。正序倒序算一种,末尾有剩余的不算。长度<=2e5
直接枚举每种分割方案,子串(l,r)的哈希值就是(hash[r]-hash[l-1]*x^(r-l+1))mod p,正着反着都要做,然后再对产生的哈希值做个哈希判重,总复杂度nlogn。
据说这题直接自然溢出就能过,我到底为什么写了个双取模而且还非要用pbds哈希表。。。时限10秒跑了9.388秒,差点就卡不过去了23333

#include<cstdio>#include<ext/pb_ds/assoc_container.hpp>#define gm 200005#ifdef ONLINE_JUDGE#define null_type null_mapped_type#endif#define pow __pow__using namespace __gnu_pbds;typedef long long ll;size_t n;ll a[gm];struct pair{    ll a,b;    pair(const ll &a=0,const ll &b=0):a(a),b(b){}    inline pair operator + (const ll &y) const    {return pair(a+y,b+y);}    inline pair operator + (const pair &y) const    {return pair(a+y.a,b+y.b);}    inline pair operator - (const pair &y) const    {return pair(a-y.a,b-y.b);}    inline pair operator * (const ll &y) const    {return pair(a*y,b*y);}    inline pair operator * (const pair &y) const    {return pair(a*y.a,b*y.b);}    inline pair operator % (const pair &y) const    {return pair(a%y.a,b%y.b);}    inline bool operator == (const pair &y) const    {return a==y.a&&b==y.b;}}z[gm],f[gm],pow[gm];struct func{    inline size_t operator () (const pair &x) const    {        static std::tr1::hash<ll> h;        return h(ll(h(x.a))<<32|h(x.b));    }};const pair m(10000019ll,10000079ll);int maxn=0;int ks[gm],top;inline pair getz(int fr,int ta){    pair p=z[ta]-z[fr-1]*pow[ta-fr+1];    return (p%m+m)%m;}inline pair getf(int fr,int ta){    pair p=f[fr]-f[ta+1]*pow[ta-fr+1];    return (p%m+m)%m;}inline size_t count(int x){    static gp_hash_table<pair,null_type,func> tb;    tb.clear();    pair p,q;    size_t res=0;    for(int i=x;i<=n;i+=x)    {        p=getz(i-x+1,i);        q=getf(i-x+1,i);        if(tb.find(p)==tb.end()&&tb.find(q)==tb.end())        tb.insert(p),tb.insert(q),++res;    }    return res;}int main(){    pow[0]=pair(1,1);    scanf("%u",&n);    for(size_t i=1;i<=n;++i)    {        scanf("%lld",a+i);        z[i]=(z[i-1]*1313131+a[i])%m;    }    for(size_t i=n;i;--i)    f[i]=(f[i+1]*1313131+a[i])%m;    for(size_t i=1;i<=n;++i)    {        pow[i]=(pow[i-1]*1313131)%m;        size_t cnt=count(i);        if(cnt>maxn)        {            maxn=cnt;            ks[top=0]=i;        }        else if(cnt==maxn)        ks[++top]=i;    }    printf("%d %d\n",maxn,top+1);    for(int i=0;i<top;++i)    printf("%d ",ks[i]);    printf("%d\n",ks[top]);    return 0;}
0 0