bzoj4650: [Noi2016]优秀的拆分
来源:互联网 发布:scratch儿童学编程 编辑:程序博客网 时间:2024/05/20 06:36
此题有95分暴力。。。
发现AABB的统计相当于对AA的统计。于是可以计算出每个点左侧为AA的方案数。枚举|A|,将字符串分成长度为|A|的小段,当AA中点在小段中的情况可以利用SA+rmq,O(1)求。于是就能在O(n/1+n/2+...+n/n)=O(nlogn)内求解。
#include<iostream>#include<cstdio>#include<cstring>#define N 80005using namespace std;int n,T,A[N],B[N],lg[N],bit[20];long long Ans;struct SuffixArray{char a[N];int SA[N],Rk[N],Ht[N],X[N],Y[N],v[N],Min[N][20];void GetSA(int n,int m=256){int *x=X,*y=Y,i,p,j;memset(v,0,sizeof v);for(i=1;i<=n;i++)v[x[i]=a[i]]++;for(i=1;i<=m;i++)v[i]+=v[i-1];for(i=n;i>=1;i--)SA[v[x[i]]--]=i;for(i=1;i<=n;i<<=1,m=p){p=0;memset(v,0,sizeof v);for(j=n-i+1;j<=n;j++)y[++p]=j;for(j=1;j<=n;j++)if(SA[j]>i)y[++p]=SA[j]-i;for(j=1;j<=n;j++)v[x[y[j]]]++;for(j=1;j<=m;j++)v[j]+=v[j-1];for(j=n;j>=1;j--)SA[v[x[y[j]]]--]=y[j];swap(x,y);p=1;x[SA[1]]=1;for(j=2;j<=n;j++)if(y[SA[j-1]]==y[SA[j]]&&y[SA[j-1]+i]==y[SA[j]+i]) x[SA[j]]=p;else x[SA[j]]=++p;if(p>=n)break;}}void GetHt(int n){int k=0;for(int i=1;i<=n;i++)Rk[SA[i]]=i;for(int i=1;i<=n;i++){if(k)k--;int j=SA[Rk[i]-1];while(i+k<=n&&j+k<=n&&a[i+k]==a[j+k])k++;Ht[Rk[i]]=k;}}void Get(int n){memset(SA,0,sizeof SA);memset(Ht,0,sizeof Ht);memset(Rk,0,sizeof Rk);memset(X,0,sizeof X);memset(Y,0,sizeof Y);memset(Min,0,sizeof Min);GetSA(n);GetHt(n);for (int i=1;i<=n;i++)Min[i][0]=Ht[i];for (int i=1;i<=15;i++)for (int j=1;j<=n;j++)Min[j][i]=min(Min[j][i-1],Min[j+bit[i-1]][i-1]);}int lcp(int x,int y){if (Rk[x]>Rk[y]) swap(x,y);x=Rk[x];y=Rk[y];int t=lg[y-x];return min(Min[x+1][t],Min[y-bit[t]+1][t]);}}S1,S2;int main(){bit[0]=1;for (int i=1;i<=15;i++) bit[i]=bit[i-1]<<1;for (int i=0,j=1,next=2;i<=15;i++,next<<=1)for (;j<=next;j++) lg[j]=i;scanf("%d",&T);while(T--){Ans=0;memset(A,0,sizeof A);memset(B,0,sizeof B);scanf("%s",S1.a+1);n=strlen(S1.a+1);for (int i=1;i<=n;i++) S2.a[n-i+1]=S1.a[i];S1.Get(n);S2.Get(n);for (int i=1;i<=n/2;i++){for (int j=1;j+i<=n;j+=i){int x=S1.lcp(j,j+i),y=S2.lcp(n-j+1,n-j-i+1);int l=max(j,j-y+i),r=min(j+i,j+x)-1;if (l<=r){A[l+i]++;A[r+i+1]--;B[l-i]++;B[r-i+1]--;}}}for (int i=1;i<=n;i++)A[i]+=A[i-1],B[i]+=B[i-1];for (int i=1;i<=n;i++)Ans+=A[i]*B[i];printf("%lld\n",Ans);}}
0 0
- bzoj4650: [Noi2016]优秀的拆分
- [BZOJ4650][NOI2016]优秀的拆分-后缀数组
- [后缀数组] BZOJ4650: [Noi2016] 优秀的拆分
- [BZOJ4650][NOI2016]优秀的拆分 各数据点解法
- 【NOI2016】优秀的拆分
- 4650: [Noi2016]优秀的拆分
- 【后缀数组】[NOI2016]优秀的拆分
- bzoj 4650: [Noi2016]优秀的拆分
- BZOJ 4650([Noi2016]优秀的拆分-SA)
- NOI2016 优秀的拆分 后缀数组
- NOI2016 优秀的拆分 后缀数组
- NOI2016优秀的拆分 后缀数组
- 【NOI2016】优秀的拆分(95分)
- [UOJ P219][NOI2016]优秀的拆分[95]
- Noi2016 D1 T1 优秀的拆分 90做法
- BZOJ 4650: [Noi2016]优秀的拆分 哈希+分块
- UOJ #219 [NOI2016 D1T1] 优秀的拆分 [95分]
- [后缀数组 枚举 字符串分段] BZOJ 4650 [Noi2016]优秀的拆分
- java容器类---HashMap、HashSet
- [平衡树] mingap
- 还是畅通工程(最小生成树)
- HTML标签属性总结+页面中模块跳转
- LA 4726 Average(单调队列)
- bzoj4650: [Noi2016]优秀的拆分
- 手机游戏开发中如何选择适合的纹理格式
- 【高性能】Mellanox交换机基本设置
- Java类加载器总结
- 一个新的开始!
- 当遇到error: stray '\241' in program错误的解决方法
- java 多线程之Sychronization的三种使用情况
- POJ 1125 Stockbroker Grapevine
- Android应用开发SharedPreferences存储数据的使用方法