题目大意:给出一个串,求按每几个一组的分割方式可以得到最多的不同子串。正序倒序算一种,末尾有剩余的不算。长度<=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;
}