bzoj4199 [Noi2015]品酒大会 后缀数组+并查集
来源:互联网 发布:淘宝实体店加盟条件 编辑:程序博客网 时间:2024/05/22 17:20
题目大意:
定义字符串s的两个子串为r相似的当起始位置不同的两个长度为r子串完全相同。
第一问: 对于每一个r,求出r相似的子串有多少对,0<=r
#include <cstdio>#include <algorithm>#include <iostream>#define N 320000using namespace std;typedef long long LL;const LL INF=0x3f3f3f3f;inline int Min(int x,int y) { return x<y?x:y; }inline int Max(int x,int y) { return x>y?x:y; }inline LL Max(LL x,LL y) { return x>y?x:y; }int n,tot;LL cnt[N],tcnt,ans[N],tmax=-INF*INF;int f[N],mx[N],cm[N],sz[N],a[N],mi[N],ci[N];int sa[N],rnk[N],h[N],tmp[N],sum[N],X[N],Y[N];char s[N];int findie(int c){ if(f[c]!=c) f[c]=findie(f[c]); return f[c];}void Union(int x,int y){ int t1=findie(x); int t2=findie(y); if(sz[t2]>sz[t1]) swap(t1,t2); tcnt+=1ll*sz[t1]*sz[t2]; f[t2]=t1; sz[t1]+=sz[t2]; if(mx[t2]>mx[t1]) cm[t1]=mx[t1],mx[t1]=mx[t2]; else if(mx[t2]>cm[t1]) cm[t1]=mx[t2]; if(cm[t2]>cm[t1]) cm[t1]=cm[t2]; if(mi[t2]<mi[t1]) ci[t1]=mi[t1],mi[t1]=mi[t2]; else if(mi[t2]<ci[t1]) ci[t1]=mi[t2]; if(ci[t2]<ci[t1]) ci[t1]=ci[t2]; tmax=Max(tmax,1ll*mx[t1]*cm[t1]); tmax=Max(tmax,1ll*mi[t1]*ci[t1]); return;}void get_rank(){ for(int i=0;i<=127;i++) sum[i]=0; for(int i=1;i<=tot;i++) sum[s[i]]++; for(int i=1;i<=127;i++) sum[i]+=sum[i-1]; for(int i=tot;i>=1;i--) tmp[sum[s[i]]--]=i; for(int i=1,t=0;i<=tot;i++) { if(i==1 || s[tmp[i]]!=s[tmp[i-1]]) t++; rnk[tmp[i]]=t; } return;}void digit_sort(int key[],int order[]){ for(int i=0;i<=tot;i++) sum[i]=0; for(int i=1;i<=tot;i++) sum[key[i]]++; for(int i=1;i<=tot;i++) sum[i]+=sum[i-1]; for(int i=tot;i>=1;i--) tmp[sum[key[order[i]]]--]=order[i]; for(int i=1;i<=tot;i++) order[i]=tmp[i];}void get_height(){ int j,k; for(int i=1;i<=tot;i++) { if(rnk[i]==1) continue; k=Max(h[rnk[i-1]]-1,0); j=sa[rnk[i]-1]; while(s[i+k]==s[j+k]) k++; h[rnk[i]]=k; }}void Suffix_Array(){ get_rank(); for(int j=1;j<=tot;j<<=1) { for(int i=1;i<=tot;i++) { sa[i]=i; X[i]=rnk[i]; Y[i]=i+j<=tot?rnk[i+j]:0; } digit_sort(Y,sa); digit_sort(X,sa); for(int i=1,t=0;i<=tot;i++) { if(i==1 || X[sa[i]]!=X[sa[i-1]] || Y[sa[i]]!=Y[sa[i-1]]) t++; rnk[sa[i]]=t; } } get_height();}bool cmp(int x,int y) { return h[x]>h[y]; }int main(){ scanf("%d",&n); tot=n; scanf("%s",s+1); for(int i=1;i<=n;i++) scanf("%d",&a[i]); Suffix_Array(); for(int i=1;i<=n;i++) { f[i]=i; sz[i]=1; mx[i]=a[sa[i]]; mi[i]=a[sa[i]]; cm[i]=-INF; ci[i]=INF; tmp[i]=i; } sort(tmp+2,tmp+n+1,cmp); int now=2; for(int i=n-1;i>=0;i--) { while(now<=n && h[tmp[now]]==i) { Union(tmp[now],tmp[now]-1); now++; } cnt[i]=tcnt; ans[i]=tcnt?tmax:0; } for(int i=0;i<n;i++) printf("%lld %lld\n",cnt[i],ans[i]); return 0;}
阅读全文
0 0
- [BZOJ4199][Noi2015]品酒大会(后缀数组+并查集)
- bzoj4199 [Noi2015]品酒大会 后缀数组+并查集
- bzoj4199[luoguP2178]品酒大会[noi2015] (后缀数组+并查集)
- 【BZOJ4199】品酒大会,后缀数组+并查集维护
- [BZOJ4199][NOI2015]品酒大会 后缀数组
- [BZOJ4199][NOI2015]品酒大会-后缀数组
- [Noi2015]品酒大会|后缀数组|并查集
- BZOJ_P4199 [NOI2015] 品酒大会(后缀数组+并查集)
- bzoj 4199: [Noi2015]品酒大会 后缀数组+并查集
- [UOJ 131]【NOI2015】品酒大会:后缀数组+并查集
- 【bzoj4199】[Noi2015]品酒大会 后缀自动机
- 【NOI2015】【BZOJ4199】品酒大会
- [BZOJ4199][Noi2015]品酒大会
- [BZOJ4199] [Noi2015]品酒大会
- [bzoj4199][NOI2015]品酒大会
- BZOJ4199 [Noi2015]品酒大会
- NOI2015.品酒大会(后缀数组)
- NOI2015品酒大会 后缀数组
- Dedecms模板下载:装饰装修设计公司网站织梦模板
- Android KEYCODE键值对应大全
- 工厂方法模式 VS 简单工厂模式
- 接口与回调(相关话题:特定事件发生应该采取动作、监听)
- 关于glReadPixels的两点心得
- bzoj4199 [Noi2015]品酒大会 后缀数组+并查集
- Linux学习小结笔记
- BZOJ 4152 博弈论 解题报告
- BZOJ2463: [中山市选2009]谁能赢呢? 题解 【(?)博弈论】
- 关于drools规则引擎的环境搭建
- Python爬虫入门一之综述
- hdu3652 A-B number 数位DP
- 死锁详解
- 一.python多线程类型总结