您的位置:首页 > 其它

BZOJ2081 : [Poi2010]Beads

2015-08-05 01:01 232 查看
暴力枚举$k$,对于一个子串,计算它正着的hash值以及反着的hash值,取最小值得到其最终hash值。

对于$k$,一共有$\lfloor\frac{n}{k}\rfloor$个子串,计算出它们的最终hash值即可统计出不同子串的个数。

时间复杂度$O(n\log n)$。

#include<cstdio>
typedef long long ll;
const int N=200010,P=2333333,D=1000173169,M=1048575;
int n,i,j,pow
,a
,pre
,suf
,val
,ans,cnt,now;
inline int min(int a,int b){return a<b?a:b;}
inline int hash(int l,int r){return min((ll)(pre[r]-(ll)pre[l-1]*pow[r-l+1]%D+D)%D,(ll)(suf[l]-(ll)suf[r+1]*pow[r-l+1]%D+D)%D);}
struct E{int v;E*nxt;}*g[M+1],pool
,*cur=pool,*p;
int vis[M+1];
inline bool ins(int v){
int u=v&M;
if(vis[u]<i)vis[u]=i,g[u]=NULL;
for(p=g[u];p;p=p->nxt)if(p->v==v)return 0;
p=cur++;p->v=v;p->nxt=g[u];g[u]=p;
return 1;
}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int main(){
for(read(n),pow[0]=i=1;i<=n;i++)pow[i]=(ll)pow[i-1]*P%D;
for(i=1;i<=n;i++)read(a[i]);
for(i=1;i<=n;i++)pre[i]=(ll)((ll)pre[i-1]*P+a[i])%D;
for(i=n;i;i--)suf[i]=(ll)((ll)suf[i+1]*P+a[i])%D;
for(i=1;i<=n;i++)for(cur=pool,j=i;j<=n;j+=i)if(ins(hash(j-i+1,j)))val[i]++;
for(i=1;i<=n;i++)if(val[i]>ans)ans=val[i],cnt=1;else if(val[i]==ans)cnt++;
for(printf("%d %d\n",ans,cnt),i=1;i<=n;i++)if(val[i]==ans){
if((++now)<cnt)printf("%d ",i);
else printf("%d",i);
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: