LOJ2083 [NOI2016] 优秀的拆分 【哈希】【调和级数】
题目分析:
好题!我们发现题目实际是要求出从某个左端点开始跑出去的BB型有多少个和从某个右端点开始跑出去的AA型有多少个。
发现这个问题是对称的,所以只考虑从左端点跑出去的BB型有多少个就可以了。
我们不妨考虑长度为$k$的BB型,那么我们把字符串每$k$个化成一个整体,然后如果从$i$开始存在一个长度为$k$的BB型,就等价于$i$开始这个整体的后缀等于下一个整体的后缀,下一个整体的后缀等于下下个整体的前缀,所以我们用哈希来求出最长后缀和最长前缀就可以做了。
代码:
#include<bits/stdc++.h>
using namespace std; const int maxn = ; int n;
char str[maxn];
int pre[maxn],suf[maxn]; // longest qianzhui longest houzhui
int f[maxn],g[maxn]; namespace HASH{
int ph[][maxn],bs[][maxn];
const int base = ;
const int mod1 = ,mod2 = ;
void buildhash(){
ph[][] = ph[][] = str[]-'a'+;
bs[][] = bs[][] = ;
for(int i=;i<n;i++){
ph[][i+] = (1ll*base*ph[][i]+str[i]-'a'+)%mod1;
ph[][i+] = (1ll*base*ph[][i]+str[i]-'a'+)%mod2;
}
for(int i=;i<=n;i++) bs[][i]=1ll*bs[][i-]*base%mod1;
for(int i=;i<=n;i++) bs[][i]=1ll*bs[][i-]*base%mod2;
}
int pd(int l1,int r1,int l2,int r2){
int z1=ph[][r1+]-1ll*bs[][r1-l1+]*ph[][l1]%mod1;if(z1<)z1+=mod1;
int z2=ph[][r1+]-1ll*bs[][r1-l1+]*ph[][l1]%mod2;if(z2<)z2+=mod2;
int y1=ph[][r2+]-1ll*bs[][r2-l2+]*ph[][l2]%mod1;if(y1<)y1+=mod1;
int y2=ph[][r2+]-1ll*bs[][r2-l2+]*ph[][l2]%mod2;if(y2<)y2+=mod2;
if(z1 == y1 && z2 == y2) return true;
else return false;
}
int maxlen(int st1,int st2,int dr){
if(st2 >=n) return ;
int tl=,tr=(dr==?st1+:n-st2+);
if(str[st1] != str[st2]) return ;
while(tl < tr){
int mid = (tl+tr+)/;
int l1,r1,l2,r2;
if(dr == ){r1=st1,r2=st2;l1=st1-mid+,l2=st2-mid+;}
else{l1=st1,l2=st2;r1=st1+mid-,r2=st2+mid-;}
if(pd(l1,r1,l2,r2)) tl = mid;
else tr = mid-;
}
return tl;
}
} void init(){
memset(pre,,sizeof(pre));
memset(suf,,sizeof(suf));
memset(HASH::ph,,sizeof(HASH::ph));
memset(f,,sizeof(f));
memset(g,,sizeof(g));
} void work(){
HASH::buildhash();
for(int i=;i<=n/;i++){
int k = ;
for(int j=;j<n;j+=i){
k++;
if(j+i < n){pre[k] = min(i,HASH::maxlen(j,j+i,));}
if(j-i >=){suf[k] = min(i,HASH::maxlen(j-,j+i-,));}
}
for(int j=,st=i;j<=k;j++,st+=i){
if(pre[j] + suf[j] < i || suf[j] == ) continue;
int l = st-suf[j],r = min(st-,(st-i)+pre[j]);
f[l]++; f[r+]--;
}
for(int j=,st=;j<k;j++,st+=i){
if(pre[j] + suf[j] < i || pre[j] == ) continue;
int l = max(st+i,(st+i-+(i-suf[j]))),r = (st+i-+pre[j]);
g[l]++; g[r+]--;
}
for(int j=;j<=k;j++) pre[j] = suf[j] = ;
}
for(int i=;i<n;i++) f[i] = f[i-] + f[i];
for(int i=;i<n;i++) g[i] = g[i-] + g[i];
long long ans = ;
for(int i=;i<n;i++){ans += 1ll*f[i]*g[i-];}
printf("%lld\n",ans);
} int main(){
int Tmp; scanf("%d",&Tmp);
while(Tmp--){
init();
scanf("%s",str);
n = strlen(str);
work();
}
return ;
}
LOJ2083 [NOI2016] 优秀的拆分 【哈希】【调和级数】的更多相关文章
- luogu1117 [NOI2016]优秀的拆分
luogu1117 [NOI2016]优秀的拆分 https://www.luogu.org/problemnew/show/P1117 后缀数组我忘了. 此题哈希可解决95分(= =) 设\(l_i ...
- 【BZOJ4560】[NOI2016]优秀的拆分
[BZOJ4560][NOI2016]优秀的拆分 题面 bzoj 洛谷 题解 考虑一个形如\(AABB\)的串是由两个形如\(AA\)的串拼起来的 那么我们设 \(f[i]\):以位置\(i\)为结尾 ...
- [UOJ#219][BZOJ4650][Noi2016]优秀的拆分
[UOJ#219][BZOJ4650][Noi2016]优秀的拆分 试题描述 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 A 和 B 是任意非空字符串,则我们称该字符串的这种拆分是优秀 ...
- [NOI2016]优秀的拆分(SA数组)
[NOI2016]优秀的拆分 题目描述 如果一个字符串可以被拆分为 \(AABB\) 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 \(aabaaba ...
- [NOI2016]优秀的拆分&&BZOJ2119股市的预测
[NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...
- 题解-NOI2016 优秀的拆分
NOI2016 优秀的拆分 \(T\) 组测试数据.求字符串 \(s\) 的所有子串拆成 \(AABB\) 形式的方案总和. 数据范围:\(1\le T\le 10\),\(1\le n\le 3\c ...
- 【洛谷1117_BZOJ4650】[NOI2016] 优秀的拆分(哈希_后缀数组_RMQ)
题目: 洛谷1117 分析: 定义把我校某兔姓神犇Tzz和他的妹子拆分,为"优秀的拆分" 随便写个哈希就能有\(95\)分的好成绩-- 我的\(95\)分做法比fei较chang奇 ...
- 并不对劲的bzoj4650:loj2083:uoj219:p1117:[NOI2016]优秀的拆分
题目大意 "优秀的拆分"指将一个字符串拆分成AABB的形式 十次询问,每次给出一个字符串S(\(|S|\leq3*10^4\)),求它的所有子串的优秀的拆分的方案数之和 题解 此题 ...
- BZOJ4650/UOJ219 [Noi2016]优秀的拆分
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
随机推荐
- 操作MongoDB数据库知识点
一.命令行操作mongo: 1.开启数据库 mongo 如果启动mongo报以下错误: 运行brew services start mongodb 2.创建数据库并进入实例 use test 3.查看 ...
- .NET移动开发,关于发布IOS的方法(本人亲身经历折腾很久终于成功)
前情提要:这位.NET程序员兄弟使用Smobiler开发了一个APP,尽管Smobiler云平台已经最大限度的简化了iOS应用的打包操作,但仍绕不开苹果公司强制要求的p12文件,p12文件需要开发者自 ...
- 如何發佈一個完整Node.js Module
本文會透過以下幾個段落,讓各位一步一步學習如何寫一個自已的Node.js Module並且發佈到npm package上 Node.js Module 結構 我們先建立一個 NodeModuleDem ...
- 简述在ADO中使用接口的抽象数据提供程序以及ADO.NET数据提供程序工厂模型
如何在ADO中使用接口的抽象数据提供程序 在cofig中 appSettings下,配置数据连接类型 <appSettings> <!--这个键值映射到枚举值中的某个值--> ...
- h5页面 video暂停播放 视频控件 以及当前页面只有一个可以播放效果
<!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...
- 安卓5.0系统怎么无Root激活XPOSED框架的方法
在大多团队的引流或业务操作中,基本上都需要使用安卓的强大Xposed框架,几天前,我们团队买来了一批新的安卓5.0系统,基本上都都是基于7.0以上系统,基本上都不能够获得Root的su权限,纵然一些能 ...
- 关于C++11右值引用和移动语义的探究
关于C++11右值引用和移动语义的探究
- ClickOnce一项Winform部署
先建一个Winform 控制台程序 建好后从工具箱里拖出来个 文本框 在属性中把TEXT改了 鼠标放到项目上点击右键——>属性 如下图所示,有两个发布位置. 发布位置可以选择本地文件夹,也可以选 ...
- ubuntu如何安装chromium浏览器并设置成中文版
在Ubuntu上使用APT安装Chromium有3种方法: 1.在Ubuntu软件中心输入chromium,然后在结果中选择安装即可. 2.在新立得软件包管理器中输入chromium,然后标记安装即可 ...
- Microsoft Store应用安装路径和应用推荐——如何用Linux命令操控windows
本人是cnblog萌新,刚学编程不久的菜鸟,这是我的第一篇博客,请各位轻喷 Microsoft store安装路径: 相信很多人都跟我一样有强迫症,文件找不到安装目录就不舒服.一开始在系统盘找不到Wi ...