传送门

 
题解
  听说大佬们这题都是用SA秒掉的
  然而SA的时间复杂度的确很优秀,缺点就是看不太懂……
  然后发现一位大佬用哈希华丽的过了此题,而且讲的特别清楚->这里
  我们只要考虑以每一个点结尾的$AA$串的个数$u[i]$和以每一个点开头的AA串的个数$v[i]$,答案就是$\sum _{i=1}^{n-1} u[i]*v[i+1]$
  那么考虑如何求出$u$和$v$呢
  我们考虑一下,枚举串$A$的长度$len$,然后每隔$len$个单位设置一个关键点。不难发现,每一个长度为$len*2$的$AA$串,必定经过两个关键点
  然后考虑,只要求出相邻两个关键点往前的$LCS$和往后的$LCP$,如果$LCS+LCP>=len$,就表明存在长度为$len$的$AA$串。而且不难发现,所有经过这两个关键点的长度为$len$的$AA$串,肯定是连续的!所以我们可以找到这个区间,然后用前缀和差分,就可以避免区间修改了
  说了这么多,到底怎么求$LCS$和$LCP$呢?(大佬:SA+ST表不是随便过的么)嗯,没错,二分。我们二分它们的长度,然后用哈希判断是否相等。这样虽然时间复杂度比起ST表多了个$log$,但起码更看得懂……
  时间复杂度是枚举$len$的调和级数,加上二分,为$O(nlog^2n)$
  ps:话说我也不明白调和级数是个什么玩意儿,只要知道枚举的复杂度是$\sum _{i=1}^n \frac{n}{i} =O(nlogn)$就行了……
  pps:管那么多干嘛能A不就行了么……话说这题明明纯哈希暴力就有95……某大佬讲课的时候还以这题为例嘲笑NOI近几年的出题水平(逃)
 //minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(ll x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=,mod=3e7+;
char s[N];int n;
ll hash[N],mo[N],u[N],v[N],ans;
inline ll gethash(int l,int r){
ll now=hash[l]-hash[r]*mo[r-l];
now%=mod,now+=mod,now%=mod;
return now;
}
int main(){
int T=read();mo[]=;for(int i=;i<=;++i) mo[i]=mo[i-]*%mod;
while(T--){
n=;char ch;
while((ch=getc())!='\n') s[++n]=ch;
memset(u,,sizeof(u)),memset(v,,sizeof(v));
hash[n+]=;
for(int i=n;i;--i) (hash[i]=hash[i+]*+s[i]-'a'+)%=mod;
for(int L=;L*<=n;++L){
for(int i=L<<;i<=n;i+=L){
if(s[i]!=s[i-L]) continue;
int l=,r=L,last=i-L,pos=;
//二分查找lcp和lcs
while(l<=r){
int mid=l+r>>;
if(gethash(last-mid+,last+)==gethash(i-mid+,i+)) pos=mid,l=mid+;
else r=mid-;
}
int head=i-pos+;
l=,r=L,pos=;
while(l<=r){
int mid=l+r>>;
if(gethash(last,last+mid)==gethash(i,i+mid)) pos=mid,l=mid+;
else r=mid-;
}
int tail=i+pos-;
head=max(head+L-,i);//防止越过两块
tail=min(tail,i+L-);//防止跑到后面的块
if(head<=tail){
++u[head-*L+],--u[tail+-*L+];
++v[head],--v[tail+];
//为了差分
//因为head-2*L+1到tail-2*L+1开头的AA串增加的
//以他们的答案都可以++
//然后以head到tail结尾的AA串也++
}
}
}
ans=;
for(int i=;i<=n;++i) u[i]+=u[i-],v[i]+=v[i-];
for(int i=;i<n;++i) ans+=v[i]*u[i+];
print(ans);
}
Ot();
return ;
}
 
 

[BZOJ]4650 优秀的拆分(Noi2016)(哈希+二分)的更多相关文章

  1. [BZOJ]4650 优秀的拆分(Noi2016)

    比较有意思的一道后缀数组题.(小C最近是和后缀数组淦上了?) 放在NOI的考场上.O(n^3)暴力80分,O(n^2)暴力95分…… 即使想把它作为一道签到题也不要这么随便啊摔(╯‵□′)╯︵┻━┻ ...

  2. 【洛谷1117_BZOJ4650】[NOI2016] 优秀的拆分(哈希_后缀数组_RMQ)

    题目: 洛谷1117 分析: 定义把我校某兔姓神犇Tzz和他的妹子拆分,为"优秀的拆分" 随便写个哈希就能有\(95\)分的好成绩-- 我的\(95\)分做法比fei较chang奇 ...

  3. bzoj 4650(洛谷 1117) [Noi2016]优秀的拆分——枚举长度的关键点+后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4650 https://www.luogu.org/problemnew/show/P1117 ...

  4. LOJ2083 [NOI2016] 优秀的拆分 【哈希】【调和级数】

    题目分析: 好题!我们发现题目实际是要求出从某个左端点开始跑出去的BB型有多少个和从某个右端点开始跑出去的AA型有多少个. 发现这个问题是对称的,所以只考虑从左端点跑出去的BB型有多少个就可以了. 我 ...

  5. loj2083 优秀的拆分 [NOI2016] SA

    正解:SA 解题报告: 我永远喜欢loj! 显然$AABB$串相当于是由两个$AA$串拼起来的,所以可以先考虑如果求出来了所有$AA$串怎么求答案? 就假如能统计出$st[i]$表示所有以$i$为开头 ...

  6. BZOJ 3796 Mushroom追妹纸 哈希+二分(+KMP)

    先把两个串能匹配模式串的位置找出来,然后标记为$1$(标记在开头或末尾都行),然后对标记数组求一个前缀和,这样可以快速查到区间内是否有完整的一个模式串. 然后二分子串(答案)的长度,每次把长度为$md ...

  7. [NOI2016]优秀的拆分 后缀数组

    题面:洛谷 题解: 因为对于原串的每个长度不一定等于len的拆分而言,如果合法,它将只会被对应的子串统计贡献. 所以子串这个限制相当于是没有的. 所以我们只需要对于每个位置i求出f[i]表示以i为开头 ...

  8. [BZOJ]4650: [Noi2016]优秀的拆分

    Time Limit: 30 Sec  Memory Limit: 512 MB Description 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 AA 和 BB 是任意非空字符串, ...

  9. 【刷题】BZOJ 4650 [Noi2016]优秀的拆分

    Description 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 AA 和 BB 是任意非空字符串,则我们称该字符串的这种拆分是优秀的.例如,对于字符串 aabaabaa,如果令 A ...

随机推荐

  1. S数据导入

    一. 职责下的视图导入先对比UAT172和PROD 177的数据,若177比172多的数据进行删除,若172比177多的数据,重新加入到177. 1.删除177多余的 搜索一个177比172多的,进行 ...

  2. 设置WebBrowser内核渲染模式

    前不久开发一个项目,是采用WebBrowser作为外壳,加载网页,由于网页是采用html5来进行开发的,当通过WebBrowser加载网页后,html5中的特性 都无法正常显示,而通过ie浏览器打开时 ...

  3. cdoj916-方老师的分身 III 【拓扑排序】

    http://acm.uestc.edu.cn/#/problem/show/916 方老师的分身 III Time Limit: 3000/1000MS (Java/Others)     Memo ...

  4. int类型与char类型的转换

    ---------siwuxie095                 Java对char类型的数据在底层是按int类型来处理的 (只是显示出来仍然是字符型)         1.int类型与char ...

  5. Unity3d收藏链接/ 小马哥视频

      Unity3d视频教程下载链接: http://pan.baidu.com/s/1kVwFhrh 密码: v6c7     第一部分  https://pan.baidu.com/share/in ...

  6. SpringBoot Actuator & SpringBoot Admin

    SpringBoot Actuator提供了很多监控和管理你的spring boot应用的HTTP或者JMX端点,并且你可以有选择地开启和关闭部分功能. 当你的spring boot应用中引入依赖之后 ...

  7. SQL SERVER性能优化综述

    SQL SERVER性能优化综述 一个系统的性能的提高,不单单是试运行或者维护阶段的性能调优的任务,也不单单是开发阶段的事情,而是在整个软件生命周期都需要注意,进行有效工作才能达到的.所以我希望按照软 ...

  8. [C++] Variable/Hex conversion

    程序编译链接原理预处理:.c -> .i gcc -E hello.c -o hello.i 编译:.i / .c -> .sgcc -S hello.i -o hello.s 汇编:.s ...

  9. XStream(xml/bean转换)

    XStream 1. 什么作用  * 可以把JavaBean转换为(序列化为)xml 2. XStream的jar包  * 核心JAR包:xstream-1.4.7.jar:  * 必须依赖包:xpp ...

  10. Qt的翻译文件QTranslator不能使用问题总结(原)

    笔者今天在自己工程中使用翻译文件,发现没有起作用,反复查找,发现是用宏定义了命名空间,生成.ts文件时,不会加上命名空间,所以生成的.qm文件在实际使用时,会无法找到对应的语句. 如果将宏定义的命名空 ...