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/ ...
随机推荐
- Webpack系列-第三篇流程杂记
系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 本文章个人理解, 只是为了理清webpack流程, 没有关注内部过多细节 ...
- MySQL 笔记整理(12) --为什么我的MySQL会“抖”一下?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 12) --为什么我的MySQL会“抖”一下? 断更了一段时间,因为这几 ...
- 微信小程序性能优化之一
性能优化 界面和业务逻辑之间事件交互小程序调用nativeNative回调小程序 图片源文件优化 渲染优化 ---------------------------------------------- ...
- css3修改浏览器scroll默认样式
最近公司的新项目.前端样式采用的蚂蚁金服的antDesign. 比较喜欢antDesign.BootStrap一类简约大方的前端样式库. 但是在页面布局上.包括一些选择框.默认的scroll样式简直丑 ...
- Vue源码实现
链接1:https://www.cnblogs.com/tiedaweishao/p/8933153.html 链接2:https://www.cnblogs.com/erbingbing/p/647 ...
- PHP下CodeIgniter框架连接读取MS Access数据库文件
cI用的是3.0版本,测试用的access为.mdb文件,php要读取Access数据库有两种驱动,一种的odbc,一种是pdo_odbc,两种都可以链接,但是一般会更推荐pdo_odbc, 要想ph ...
- Python正则表达式很难?一篇文章搞定他,不是我吹!
1. 正则表达式语法 1.1 字符与字符类 1 特殊字符:.^$?+*{}| 以上特殊字符要想使用字面值,必须使用进行转义 2 字符类 1. 包含在[]中的一个或者多个字符被称为字符类,字符类在匹配时 ...
- SQLServer之创建Transact-SQL游标
什么是游标 结果集,结果集就是select查询之后返回的所有行数据的集合. 游标则是处理结果集的一种机制吧,它可以定位到结果集中的某一行,多数据进行读写,也可以移动游标定位到你所需要的行中进行操作数据 ...
- sql 按年月日统计
1.每年select year(ordertime) 年,sum(Total) 销售合计from 订单表group by year(ordertime) 2.每月select year(orderti ...
- Mysql创建和删除数据库
很久没有使用命令行操作Mysql,百度搜罗,重新整理,加强记忆,便于查询. 以下命令均在win7,64位操作系统下,cmd命令行操作: 一.创建1个Mysql 数据库 方法1:1. cmd下输入:my ...