Codeforces 356E - Xenia and String Problem(哈希)
首先显然一个 gray 串的长度只可能是 \(2^k-1\),其中 \(k\in\mathbb{Z}\)。
考虑将一个字符改成另外一个字符会对答案产生什么样的影响。显然原来包含这个字符的 gray 串的贡献都应被减掉,新出现的 gray 串的贡献又应被加上。我们分别计算两部分的贡献。
对于第一部分,由于 gray 串最多只可能有 \(n\log n\),因此我们逐一枚举它们并差分一下它们贡献。那么如何检验一个长度为 \(2^k-1\) 的字符串是否符合要求呢?考虑倍增。设 \(is_{i,j}\) 表示以 \(s_j\) 开头的长度为 \(2^i-1\) 的字符串是否符合要求,那么 \(is_{i,j}\) 为 \(1\) 当且仅当 \(is_{i-1,j},is_{i-1,j+2^{i-1}}\) 均为 \(1\),并且 \(s[j...j+2^{i-1}-2]=s[j+2^{i-1}...j+2^i-2]\),且 \(s_{j+2^{i-1}-1}\) 在 \(s[j...j+2^i-2]\) 中只出现过一次。这个很好判断。
对于第二部分,我们考虑一个长度为 \(2^{k}-1\) 字符串在修改哪些字符的情况下会变成 gray 串。分三种情况:改左边、改中间、改右边。第一种和第三种本质上是相同的,因此这里只考虑第一种和第二种。如果修改中间字符,那么要求左右两边的子串相同并且都是 gray 串,并且修改过的字符在子串中只出现一次。如果修改左边字符串中的字符,那么修改方式显然是唯一的——就是左右两部分唯一不同的字符串,可以通过二分+hash 求出 LCP 和 LCS 后知道要修改哪个字符,然后再检验下改过之后的字符串是否符合要求即可。
总之是一道不算太难的哈希练手题。
const int MAXN=1e5;
const int LOG_N=17;
int n;char s[MAXN+5];
ll d[MAXN+5],add[MAXN+5][28];
struct hsh{
int BS,MOD;
int hs[MAXN+5],pw[MAXN+5];
void init(){
for(int i=(pw[0]=1);i<=n;i++) pw[i]=1ll*pw[i-1]*BS%MOD;
for(int i=1;i<=n;i++) hs[i]=(1ll*hs[i-1]*BS+s[i])%MOD;
}
int gethash(int l,int r){return (hs[r]-1ll*pw[r-l+1]*hs[l-1]%MOD+MOD)%MOD;}
} h1,h2;
bool check(int l1,int r1,int l2,int r2){
return h1.gethash(l1,r1)==h1.gethash(l2,r2)&&
h2.gethash(l1,r1)==h2.gethash(l2,r2);
}
int occ[MAXN+5][28];
bool is[LOG_N+2][MAXN+5];
int getocc(int c,int l,int r){return occ[r][c]-occ[l-1][c];}
int getlcp(int x,int y){
int l=1,r=n-max(x,y)+1,p=0;
while(l<=r){
int mid=l+r>>1;
if(check(x,x+mid-1,y,y+mid-1)) p=mid,l=mid+1;
else r=mid-1;
} return p;
}
int getlcs(int x,int y){
int l=1,r=min(x,y),p=0;
while(l<=r){
int mid=l+r>>1;
if(check(x-mid+1,x,y-mid+1,y)) p=mid,l=mid+1;
else r=mid-1;
} return p;
}
int main(){
scanf("%s",s+1);n=strlen(s+1);
h1.BS=191;h1.MOD=998244853;h2.BS=193;h2.MOD=1004535809;
h1.init();h2.init();
for(int i=1;i<=n;i++){
for(int j=0;j<26;j++) occ[i][j]=occ[i-1][j];
occ[i][s[i]-'a']++;
}
for(int i=1;i<=n;i++) is[1][i]=1;ll sum=n;
for(int i=2;i<=LOG_N;i++) for(int j=1;j+(1<<i)-2<=n;j++){
is[i][j]=is[i-1][j]&is[i-1][j+(1<<i-1)];
if(is[i][j]){
is[i][j]&=check(j,j+(1<<i-1)-2,j+(1<<i-1),j+(1<<i)-2);
is[i][j]&=(getocc(s[j+(1<<i-1)-1]-'a',j,j+(1<<i)-2)==1);
if(is[i][j]){
int len=(1<<i)-1;sum+=1ll*len*len;
d[j]+=1ll*len*len;d[j+(1<<i)-1]-=1ll*len*len;
}
}
// printf("%d %d %d\n",i,j,is[i][j]);
}
for(int i=1;i<=n;i++) d[i]+=d[i-1];
ll dlt=0;
for(int i=2;i<=LOG_N;i++) for(int j=1;j+(1<<i)-2<=n;j++){
if(!is[i-1][j]&&!is[i-1][j+(1<<i-1)]) continue;
int len=(1<<i)-1;ll bnf=1ll*len*len;
if(is[i-1][j]&&is[i-1][j+(1<<i-1)]){
if(check(j,j+(1<<i-1)-2,j+(1<<i-1),j+(1<<i)-2)){
for(int c=0;c<26;c++) if(!getocc(c,j,j+(1<<i)-2)){
add[j+(1<<i-1)-1][c]+=bnf;
}
}
} if(is[i-1][j+(1<<i-1)]){
int lcp=getlcp(j,j+(1<<i-1)),lcs=getlcs(j+(1<<i-1)-2,j+(1<<i)-2);
if(lcp+lcs==(1<<i-1)-2){
int ori=s[j+lcp]-'a',nd=s[j+(1<<i-1)+lcp]-'a';
if(getocc(s[j+(1<<i-1)-1]-'a',j,j+(1<<i)-2)-(ori==s[j+(1<<i-1)-1]-'a')+(nd==s[j+(1<<i-1)-1]-'a')!=1);
else add[j+lcp][nd]+=bnf;
}
} if(is[i-1][j]){
int lcp=getlcp(j,j+(1<<i-1)),lcs=getlcs(j+(1<<i-1)-2,j+(1<<i)-2);
if(lcp+lcs==(1<<i-1)-2){
int ori=s[j+(1<<i-1)+lcp]-'a',nd=s[j+lcp]-'a';
if(getocc(s[j+(1<<i-1)-1]-'a',j,j+(1<<i)-2)-(ori==s[j+(1<<i-1)-1]-'a')+(nd==s[j+(1<<i-1)-1]-'a')!=1);
else add[j+(1<<i-1)+lcp][nd]+=bnf;
}
}
}
// printf("%lld\n",sum);
// for(int i=1;i<=n;i++) printf("%lld%c",d[i]," \n"[i==n]);
for(int i=1;i<=n;i++) for(int j=0;j<26;j++)
if(s[i]-'a'!=j) chkmax(dlt,-d[i]+add[i][j]);
printf("%lld\n",sum+dlt);
return 0;
}
Codeforces 356E - Xenia and String Problem(哈希)的更多相关文章
- CF356E - Xenia and String Problem
也许更好的阅读体验 \(\mathcal{Description}\) 定义一种字符串\(gray\)串满足: 长度为奇数 正中间的字母只出现一次 左右两端相同,左右两端也是gray串 一个\(gra ...
- Codeforces #541 (Div2) - E. String Multiplication(动态规划)
Problem Codeforces #541 (Div2) - E. String Multiplication Time Limit: 2000 mSec Problem Descriptio ...
- Mediocre String Problem (2018南京M,回文+LCP 3×3=9种做法 %%%千年好题 感谢"Grunt"大佬的细心讲解)
layout: post title: Mediocre String Problem (2018南京M,回文+LCP 3×3=9种做法 %%%千年好题 感谢"Grunt"大佬的细 ...
- hdu String Problem(最小表示法入门题)
hdu 3374 String Problem 最小表示法 view code#include <iostream> #include <cstdio> #include &l ...
- HDU 3374 String Problem(KMP+最大/最小表示)
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- 【HDU3374】 String Problem (最小最大表示法+KMP)
String Problem Description Give you a string with length N, you can generate N strings by left shift ...
- HDOJ3374 String Problem 【KMP】+【最小表示法】
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- HDU 3374 String Problem (KMP+最大最小表示)
HDU 3374 String Problem (KMP+最大最小表示) String Problem Time Limit: 2000/1000 MS (Java/Others) Memory ...
- String Problem hdu 3374 最小表示法加KMP的next数组
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
随机推荐
- 5分钟让你掌握Vuex,深入浅出
5分钟让你掌握Vuex,深入浅出 一.什么是Vuex? 概念:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预 ...
- 自定义ConditionalOnXX注解
一.Conditional注解介绍 对SpringBoot有足够了解的小伙伴应该都用过Conditional系列注解,该注解可用在类或者方法上用于控制Bean的初始化. 常用的Conditional注 ...
- 初学Python-day12 装饰器函数
装饰器 1.概念 本质就是一个Python函数,其他函数在本身不变的情况下去增加额外的功能,装饰器的返回值是一个函数. 常用的场景:插入日志,事务处理,缓存,权限校验等. 2.普通函数回顾 1 def ...
- netty系列之:netty对http2消息的封装
目录 简介 http2消息的结构 netty对http2的封装 Http2Stream Http2Frame 总结 简介 无论是什么协议,如果要真正被使用的话,需要将该协议转换成为对应的语言才好真正的 ...
- [对对子队]会议记录4.21(Scrum Meeting12)
今天已完成的工作 吴昭邦 工作内容:基本实现改变顺序合成 相关issue:实现流水线合成系统的逻辑 相关签入:4.21签入1 梁河览 工作内容:修改设置界面bug 相关签入:4.2 ...
- 2021.10.7 NKOJ周赛总结
Ⅰ. 自描述序列 问题描述: 序列 1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,2,1,... 看似毫无规律,但若我们将相邻的数字合并 : 1,22,11,2,1,22,1 ...
- python doc os 参考
os --- 操作系统接口模块 源代码: Lib/os.py 该模块提供了一些方便使用操作系统相关功能的函数. 如果你是想读写一个文件,请参阅 open(),如果你想操作路径,请参阅 os.path ...
- 全志Linux Tina编译demoOmxVdec错误
测试裸流 Making install in demoOmxVdec make[6]: Entering directory '/home/liuxueneng/WorkCode/Homlet-Tin ...
- Spoj 2878 KNIGHTS - Knights of the Round Table | 双联通分量 二分图判定
题目链接 考虑建立原图的补图,即如果两个骑士不互相憎恨,就在他们之间连一条无向边. 显而易见的是,如果若干个骑士在同一个点数为奇数的环上时,他们就可以在一起开会.换句话说,如果一个骑士被一个奇环包含, ...
- Serverless 工程实践|自建 Apache OpenWhisk 平台
作者 | 刘宇(江昱) 前言:OpenWhisk 是一个开源.无服务器的云平台,可以在运行时容器中通过执行扩展的代码响应各种事件,而无须用户关心相关的基础设施架构. OpenWhisk 简介 Open ...