题目分析:

好题!我们发现题目实际是要求出从某个左端点开始跑出去的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] 优秀的拆分 【哈希】【调和级数】的更多相关文章

  1. luogu1117 [NOI2016]优秀的拆分

    luogu1117 [NOI2016]优秀的拆分 https://www.luogu.org/problemnew/show/P1117 后缀数组我忘了. 此题哈希可解决95分(= =) 设\(l_i ...

  2. 【BZOJ4560】[NOI2016]优秀的拆分

    [BZOJ4560][NOI2016]优秀的拆分 题面 bzoj 洛谷 题解 考虑一个形如\(AABB\)的串是由两个形如\(AA\)的串拼起来的 那么我们设 \(f[i]\):以位置\(i\)为结尾 ...

  3. [UOJ#219][BZOJ4650][Noi2016]优秀的拆分

    [UOJ#219][BZOJ4650][Noi2016]优秀的拆分 试题描述 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 A 和 B 是任意非空字符串,则我们称该字符串的这种拆分是优秀 ...

  4. [NOI2016]优秀的拆分(SA数组)

    [NOI2016]优秀的拆分 题目描述 如果一个字符串可以被拆分为 \(AABB\) 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 \(aabaaba ...

  5. [NOI2016]优秀的拆分&&BZOJ2119股市的预测

    [NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...

  6. 题解-NOI2016 优秀的拆分

    NOI2016 优秀的拆分 \(T\) 组测试数据.求字符串 \(s\) 的所有子串拆成 \(AABB\) 形式的方案总和. 数据范围:\(1\le T\le 10\),\(1\le n\le 3\c ...

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

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

  8. 并不对劲的bzoj4650:loj2083:uoj219:p1117:[NOI2016]优秀的拆分

    题目大意 "优秀的拆分"指将一个字符串拆分成AABB的形式 十次询问,每次给出一个字符串S(\(|S|\leq3*10^4\)),求它的所有子串的优秀的拆分的方案数之和 题解 此题 ...

  9. BZOJ4650/UOJ219 [Noi2016]优秀的拆分

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

随机推荐

  1. Java开发笔记(八十一)如何使用系统自带的注解

    之前介绍继承的时候,提到对于子类而言,父类的普通方法可以重写也可以不重写,但是父类的抽象方法是必须重写的,如果不重写,编译器就直接在子类名称那里显示红叉报错.例如,以前演示抽象类用法之时,曾经把Chi ...

  2. 设计模式系列6:适配器模式(Adapter Pattern)

    定义 将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.    --<设计模式>GoF UML类图 使用场景 在遗留代码复用,类 ...

  3. 008. 阻塞&非阻塞、同步&异步

    阻塞 非阻塞:关注的对象是调用者: 阻塞:调用者发起调用后,处于等待状态,直到该调用有返回: 非阻塞:调用者发起调用后,不需要等待返回,可以往下执行: 同步 异步:  关注的对象是被调用者: 同步:服 ...

  4. css3修改浏览器scroll默认样式

    最近公司的新项目.前端样式采用的蚂蚁金服的antDesign. 比较喜欢antDesign.BootStrap一类简约大方的前端样式库. 但是在页面布局上.包括一些选择框.默认的scroll样式简直丑 ...

  5. 小tips:JS的Truthy和Falsy(真值与假值)

    前言 Truthy 不等于 ture,他是指是在Boolean上下文中转换后的值为真的值.我的理解是,在javascript中所有表达式为true的值.同理Falsy指的是在javascript中所有 ...

  6. Retrofit+MVP框架封装记录篇

    当下最流行的网络请求组合,retrofit2+okhttp+rxjava+mvp 这里是封装记录篇 首先分模块,比如登录 先来说封装后的使用 package com.fragmentapp.login ...

  7. 网络爬虫BeautifulSoup库的使用

    使用BeautifulSoup库提取HTML页面信息 #!/usr/bin/python3 import requests from bs4 import BeautifulSoup url='htt ...

  8. row_number() over()分页查询

    1.首先讲下row_number() over() 是干什么的? 是一个分析函数,会在数据表生成一个排序列. 案例SQL: select ROW_NUMBER() over(order by book ...

  9. HelloHibernate的创建过程

    文章提纲 安装与配置 开发小结 建立项目 配置项目 创建代码 执行项目 安装与配置 JDK的安装:建议使用JRE 1.8以上: SQL Server 2000的安装:建议SQL Server 2000 ...

  10. [已解决]ValueError: row index was 65536, not allowed by .xls format

    报错: ValueError: row index was 65536, not allowed by .xls format 解决方案: xlrd和xlwt处理的是xls文件,单个sheet最大行数 ...