Codeforces 961F - k-substrings(二分+哈希)
介绍一种奇怪的 \(\Theta(n\log n)\) 的奇怪做法。
注意到这个“border 的长度必须是奇数”的条件非常奇怪,同时我们待求解的字符串也有一些比较奇妙的性质——它们的左右端点都关于中线轴对称,即 \(l+r=n+1\)。我们考虑 border 的性质与 \(l+r=n+1\) 的条件联系起来。对于一个 \(s[l...r]\) 的长度为 \(len\) 的 border(\(len\) 为奇数),假设 \(r'=l+len-1,l'=r-len+1\),那么必然有 \(s_l\) 与 \(s_{l'}\)、\(s_{l+1}\) 与 \(s_{l'+1}\),……,\(s_r\) 与 \(s_{r'}\) 均匹配。在下文中,用“左 border”代替 \(s[l...r']\),“右 border”代替 \(s[l'...r]\)。
然后我们惊奇地发现,如果我们记 \(m_l=\dfrac{l+r'}{2},m_r=\dfrac{l'+r}{2}\),那么有 \(m_l+m_r=n+1\),并且 \(m_l\) 与 \(m_r\) 也应匹配。画出图来大概是这个样子,其中黑线为中线 \(\dfrac{n+1}{2}\),绿线为左 border 的两个端点,褐色的线为右 border 的两个端点:
因此我们考虑枚举 \(m_l\),那么可以发现,由于 \(m_l\) 是左 border 的中点,\(m_r\) 是右 border 的中点,因此在上图中,两段黄色部分对应的字符串必须相同,两段紫色部分也同理,并且黄色和紫色部分长度也应相同。也就是说 \(s[l...m_l],s[l'...m_r]\) 是 \(s[1...m_l],s[1...m_r]\) 两段前缀的 LCS,\(s[m_l...r'],s[m_r...r]\) 是 \([l...n],s[r...n]\) 的两段后缀的 LCP,也就是说,我们可以通过二分+哈希找到 \(s[l...m_l]\) 这段区间的范围,不妨设其为 \([1,mn]\)。得到了这些信息之后,又该怎样求解答案呢?对于每个左端点 \(l\),我们考虑设 \(M_l\) 表示 \([l,n+1-l]\) 的所有长度为奇数的 border 中,左 border 的中点的最大值,显然只要左 border 的中点越靠右,对应的 border 长度也就越大,而不难发现,我们求出 \(m_l,m_r\) 可以延伸的范围 \([1,mn]\) 之后,操作等价于令 \(M_{m_l-mn+1},M_{m_l-mn+2},\cdots,M_{m_l}\) 均对 \(m_l\) 取 \(\max\),差分一下用个 set
维护即可。
const int MAXN=1e6;
const int MOD=1004535809;
const int BS=193;
int n;char s[MAXN+5];
int pw[MAXN+5],hsh[MAXN+5];
vector<int> add[MAXN+5],del[MAXN+5];
int gethsh(int l,int r){return (hsh[r]-1ll*hsh[l-1]*pw[r-l+1]%MOD+MOD)%MOD;}
int main(){
scanf("%d%s",&n,s+1);
for(int i=(pw[0]=1);i<=MAXN;i++) pw[i]=1ll*pw[i-1]*BS%MOD;
for(int i=1;i<=n;i++) hsh[i]=(1ll*hsh[i-1]*BS+s[i])%MOD;
for(int i=1;i<=n>>1;i++) if(s[i]==s[n+1-i]){
int l=1,r=i,L=0,R=0;
while(l<=r){
int mid=l+r>>1;
if(gethsh(i-mid+1,i)==gethsh(n+1-i-mid+1,n+1-i)) L=mid,l=mid+1;
else r=mid-1;
} l=1,r=i;
while(l<=r){
int mid=l+r>>1;
if(gethsh(i,i+mid-1)==gethsh(n+1-i,n-i+mid)) R=mid,l=mid+1;
else r=mid-1;
} int mn=min(L,R);
add[i-mn+1].pb(i);del[i+1].pb(i);
} multiset<int> st;
for(int i=1;i<=(n+1>>1);i++){
for(int x:add[i]) st.insert(x);
for(int x:del[i]) st.erase(st.find(x));
if(st.empty()) printf("-1 ");
else printf("%d ",((*st.rbegin())-i+1)*2-1);
}
return 0;
}
Codeforces 961F - k-substrings(二分+哈希)的更多相关文章
- codeforces 1269E K Integers (二分+树状数组)
链接:https://codeforces.com/contest/1269/problem/E 题意:给一个序列P1,P2,P3,P4....Pi,每次可以交换两个相邻的元素,执行最小次数的交换移动 ...
- 2016vijos 1-1 兔子的字符串(后缀数组 + 二分 + 哈希)
题意: 给出一个字符串,至多将其划分为n部分,每一部分取出字典序最大的子串ci,最小化 最大的ci 先看一个简化版的问题: 给一个串s,再给一个s的子串t,问能否通过将串划分为k个部分,使t成为划分后 ...
- Codeforces 109D String Transformation 字符串 哈希 KMP
原文链接https://www.cnblogs.com/zhouzhendong/p/CF109D.html 题目传送门 - CF109D 题意 给定两个字符串 $a,b$ ,求一组 $i,j$ 使得 ...
- POJ 2774 后缀数组 || 二分+哈希
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 35607 Accepted: 14 ...
- [Codeforces 1199C]MP3(离散化+二分答案)
[Codeforces 1199C]MP3(离散化+二分答案) 题面 给出一个长度为n的序列\(a_i\)和常数I,定义一次操作[l,r]可以把序列中<l的数全部变成l,>r的数全部变成r ...
- CodeForces 670D1 暴力或二分
今天,开博客,,,激动,第一次啊 嗯,,先来发水题纪念一下 D1. Magic Powder - 1 This problem is given in two versions that diff ...
- codeforces 895B XK Segments 二分 思维
codeforces 895B XK Segments 题目大意: 寻找符合要求的\((i,j)\)对,有:\[a_i \le a_j \] 同时存在\(k\),且\(k\)能够被\(x\)整除,\( ...
- codeforces 803D Magazine Ad(二分+贪心)
Magazine Ad 题目链接:http://codeforces.com/contest/803/problem/D ——每天在线,欢迎留言谈论. 题目大意: 给你一个数字k,和一行字符 例: g ...
- [JSOI2008]Blue Mary的战役地图(二分+哈希)
Blue Mary最近迷上了玩Starcraft(星际争霸) 的RPG游戏.她正在设法寻找更多的战役地图以进一步提高自己的水平. 由于Blue Mary的技术已经达到了一定的高度,因此,对于用同一种打 ...
随机推荐
- pycharm 服务器连接及一些问题解决
主要介绍一下如何使用pycharm连接服务器并在服务器上炼丹,并对遇到的一个小问题进行说明. 目录 1,SSH连接 2,linux常用命令 3,配置anaconda 4,运行代码 5,一个常见错误 1 ...
- GPIO原理与配置(跑马灯,蜂鸣器,按键)
一.STM32 GPIO固件库函数配置方法 1. 根据需要在项目中删掉一些不用的固件库文件,保留有用的固件库文件 2. 在stm32f10x_conf.h中注释掉这些不用的头文件 3. STM32的I ...
- [CSP-S2021] 括号序列
链接: P7914 题意: 有一堆规则,然后判断给定字符串有多少种填法符合规则. 分析: 一眼区间dp,状态数 \(n^2\),我们来分析这些规则. 把这些规则分成三类,第一类可以预处理出区间是否能表 ...
- max-points-on-a-line leetcode C++
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...
- 面试官:JavaScript如何实现数组拍平(扁平化)方法?
面试官:JavaScript如何实现数组拍平(扁平化)方法? 1 什么叫数组拍平? 概念很简单,意思是将一个"多维"数组降维,比如: // 原数组是一个"三维" ...
- PE头详细分析
目录 PE头详细分析 0x00 前言 0x01 PE文件介绍 0x02 PE头详细分析 DOS头解析 NT头解析 标准PE头解析 可选PE头解析 可选PE头结构 基址 代码段地址 数据段地址 OEP程 ...
- loto仪器_如何模拟输出凸轮轴和曲轴波形_用任意波形信号源SIG852?
loto仪器_如何模拟输出凸轮轴和曲轴波形_用任意波形信号源SIG852? 在汽车传感器的波形检测应用中,有时候需要模拟各种汽车传感器的输出信号,用来驱动和监测对应的执行机构或者电路是否正常,这其中, ...
- #web开发# 知道cookie hostonly属性的请举手。
Cookie常见姿势.疑难梳理 目前w3c定义浏览器存放每个cookie需要包含以下字段: cookie属性 基本描述 举例 备注 name=value cookie键值对 id=a3fWa expi ...
- IDEA maven Run Maven 启动方式
首先想要使用 Run Maven 启动需要在IDEA设置里找到plugins 在plugins窗口下面找到Browse Repositories 打开Browse Repositories 下载 ...
- 菜鸡的Java笔记 第三十三 - java 泛型
泛型 GenericParadigm 1.泛型的产生动机 2.泛型的使用以及通配符 3.泛型方法的使用 JDK1.5 后的三大主 ...