BZOJ2342:[SHOI2011]双倍回文
浅谈\(Manacher\):https://www.cnblogs.com/AKMer/p/10431603.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2342
假设我已经将原字符串的\(p\)数组求好了。
双倍回文肯定是#\(W\)#\(W^R\)#\(W\)#\(W^R\)#
我们枚举中间一个#,求在它的回文半径的一半以内最靠前的第一个满足\(i+p_i-1\geqslant pos\)的第一个#,那么肯定第三个#也是存在的,然后用这个更新答案即可。
怎么快速找到第一个#呢?并查基优化即可。如果一个位置的\(i+p_i-1< pos\)那么显然这个位置也不可能作为后面的#号的第一个#,直接用并查基把他和下一个位置合起来即可。
时间复杂度:\(O(\alpha n)\)
空间复杂度:\(O(n)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e6+5;
int n,ans;
char s[maxn];
int p[maxn],fa[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
int find(int x) {
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
int main() {
n=read();
scanf("%s",s+1);
for(int i=n;i;i--)
s[i<<1]=s[i],s[(i<<1)-1]='#';
s[n<<1|1]='#',s[0]='$',n=n<<1|1;
int id=0,mx=0;
for(int i=1;i<=n;i+=2)fa[i]=i;
for(int i=1;i<=n;i++) {
p[i]=i<=mx?min(mx-i+1,p[(id<<1)-i]):1;
while(s[i-p[i]]==s[i+p[i]])p[i]++;
if(i+p[i]-1>mx)id=i,mx=i+p[i]-1;
if(s[i]=='#'&&p[i]>=5) {
int st=i-p[i]/2;if(st%2==0)st|=1;
for(int j=find(st);j<=i;j=find(j+2))
if(j+p[j]<=i) fa[j]=find(j+2);
else {ans=max(ans,(i-j)<<1);break;}
}
}
printf("%d\n",ans);
return 0;
}
根据洛谷一大佬的题解,此题有\(O(n)\)做法,只需要在\(mx\)被更新的时候枚举旧的\(mx\)到新的\(mx\)之间的点做双倍回文的右端点,新的\(id\)作为双倍回文的中点,然后判断对称过去是不是个回文即可。这样子做双倍回文肯定会被枚举到,并且枚举的总时间就是\(mx\)的改变量。
时间复杂度:\(O(n)\)
空间复杂度:\(O(n)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e6+5;
int n,ans;
int p[maxn];
char s[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
int main() {
n=read();
scanf("%s",s+1);
for(int i=n;i;i--)
s[i<<1]=s[i],s[(i<<1)-1]='#';
s[n<<1|1]='#',s[0]='$',n=n<<1|1;
int id=0,mx=0;
for(int i=1;i<=n;i++) {
p[i]=i<=mx?min(mx-i+1,p[(id<<1)-i]):1;
while(s[i-p[i]]==s[i+p[i]])p[i]++;
if(i+p[i]-1>mx) {
if(s[i]=='#') {
int st=mx+1;if(s[st]!='#')st++;
for(int j=st;j<=i+p[i]-1;j+=2) {
int pos=i+(j-i)/2;pos=(i<<1)-pos;
if(s[pos]=='#'&&p[pos]+pos-1>=i)ans=max(ans,j-i);
}
}
id=i,mx=i+p[i]-1;
}
}
printf("%d\n",ans);
return 0;
}
BZOJ2342:[SHOI2011]双倍回文的更多相关文章
- BZOJ2342 Shoi2011 双倍回文 【Manacher】
BZOJ2342 Shoi2011 双倍回文 Description Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输 ...
- BZOJ2342: [Shoi2011]双倍回文
2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 923 Solved: 317[Submit][Status ...
- BZOJ2342[Shoi2011]双倍回文——回文自动机
题目描述 输入 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. 输出 输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文 ...
- bzoj千题计划306:bzoj2342: [Shoi2011]双倍回文 (回文自动机)
https://www.lydsy.com/JudgeOnline/problem.php?id=2342 解法一: 对原串构建回文自动机 抽离fail树,从根开始dfs 设len[x]表示节点x表示 ...
- BZOJ2342:[SHOI2011]双倍回文(Manacher)
Description Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输出文件只有一行,即:输入数据中字符串的最长 ...
- [BZOJ2342] [Shoi2011]双倍回文(manacher)
传送门 manacher...... 先跑一边manacher是必须的 然后枚举双倍回文串的对称轴x 把这个双倍回文串分成4段,w wR w wR 发现,只有当 y <= x + p[x] / ...
- bzoj2342: [Shoi2011]双倍回文 pam
题解:先建pam,然后在fail树上dfs,从上到下的链如果有当前长度最远回文串的一半,那么更新答案 //#pragma GCC optimize(2) //#pragma GCC optimize( ...
- 【BZOJ-2342】双倍回文 Manacher + 并查集
2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1799 Solved: 671[Submit][Statu ...
- 【BZOJ2342】双倍回文(回文树)
[BZOJ2342]双倍回文(回文树) 题面 BZOJ 题解 构建出回文树之后 在\(fail\)树上进行\(dp\) 如果一个点代表的回文串长度为\(4\)的倍数 并且存在长度为它的一半的回文后缀 ...
- 2018.06.30 BZOJ 2342: [Shoi2011]双倍回文(manacher)
2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符串 ...
随机推荐
- 20145239杜文超《网络对抗》- Web基础
20145239杜文超<网络对抗>- Web基础 基础问题回答 1.什么是表单? 表单是一个包含表单元素的区域. 表单元素是允许用户在表单中(比如:文本域.下拉列表.单选框.复选框等等)输 ...
- Java中Arrays.sort()和Collections.sort()
1.简单示例 sort方法的使用非常的简单明了,下面的例子中,先定义一个比较Dog大小的Comparator,然后将其实例对象作为参数传给sort方法,通过此示例,你应该能够快速掌握Arrays.so ...
- 克隆VMware虚拟机
虚拟机使用过程需要用到多个进行实验.重新安装时间又太长,通过vmware虚拟机自带软件能够很好的快速克隆出完全相同的系统. 环境:关闭VMware,不要在开启状态哦~ 步骤: 选中需要被克隆的系统 菜 ...
- INSPIRED启示录 读书笔记 - 第26章 合理运用敏捷方法
十大秘诀 1.产品经理即是产品负责人,他代表了客户的需求,因而需要与产品开发团队保持密切的联系,协助督促开发进程,及时解决出现的问题 2.使用敏捷方法绝不等于省略产品规划.规划周期应该适度缩短,反复迭 ...
- MySQL/MariaDB数据库备份与恢复之mysqlpump入门操作
创建测试用表:MariaDB [music]> create table summary(id int,info char(128));Query OK, 0 rows affected (0 ...
- 【BZOJ1854】游戏[SCOI2009](神奇贪心+并查集)
这道题和今年GDKOI的Day2T2很像(然而gdkoi的题用网络流可以A,这道题只能拿30). 网址:http://www.lydsy.com/JudgeOnline/problem.php?id= ...
- CentOS 7 安装 docker-compose
compose是用来在docker中定义和运行复杂应用的小工具,比如在一个文件中定义多个容器,只用一行命令就可以让一切就绪并运行. 安装pip: 这里显示,找不到相应的包?? 说没有python-pi ...
- HRBUST 1717 字典树模板
之前写字典树虽然很熟也能变化 但是一直是到了场上再乱写 写的很长 于是准备写个短点的板子 于是选了个水题 然而写出了1W个bug insert和query反而写的没什么问题.. L c[100050] ...
- QT 文本html显示格式的问题,如在QTextBrowser.setText用tr(),其中为html格式
QObject::tr("<h1><font color = green>%1</font>的人品指数:<font color = orange&g ...
- 理解面向消息的中间件和 JMS
本章知识点: 企业消息和面向消息的中间件 理解 Java Message Service(JMS) 使用 JMS APIs 发送和接收消息 消息驱动 bean 的一个例子 简介 一般来说,掌握了企业级 ...