题意:有一个长度为\(n\)的字符串,求它最长的子串\(s\)满足\(s\)是长度为4的倍数的回文串,且它的前半部分和后半部分都是回文串。

\(n \leq 5 \times 10^5\)

首先,显然要用manacher求出以每一位为中心的最长回文串。考虑枚举\(s\)最中间的一个位置\(i\),且以其为中心的最长回文串长度为\(2 r_i\),那么,前半部分的中心\(j\)就必须在\([i - \lfloor \frac {r_i} {2} \rfloor,i)\)的区间上,并且\(i - j \leq r_j\)。当然,我们会贪心地选择这个区间上最左边的合法的\(j\)。并且,只要某个\(j\)在当前中心为\(i\)的时候满足\(i - j \leq r_j\),那么,对于所有\(k \leq i\),都有\(k - j \leq r_j\)。

于是,只要从左往右移动\(i\),每次删除移动后非法的\(j\),问题就变成实现一个数据结构,支持:

  • 删除一个元素
  • 求一个值后继

这可以轻易地以\(O(n \log n)\)的时间复杂度实现,但我们希望一个更优的算法。

考虑一个元素如果每删除了,那么受影响的就只有以它为后继的值。这些值的后继会变成它们后继的后继。设\(S_i\)表示以元素\(i\)为后继的所有值的集合,那么,删除\(i\)后,我们只要把\(S_i\)合并到\(S_j\)里面就可以了。(元素\(j\)是元素\(i\)的后继)

因此,我们用并查集维护一下就好了。这个巧妙的技巧应该会在本题卡常时发挥作用。

时间复杂度\(O(n \alpha(n))\)

#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
int n,len[N * 2],r[N];
char s[N];
void manacher() {
for (int i = 2 ; i <= (n << 1) ; ++ i) {
int l = i >> 1, r = (i + 1) >> 1;
while (s[l - len[i]] == s[r + len[i]] && l - len[i] >= 1 && r + len[i] <= n)
++ len[i];
l = i - 1, r = i + 1;
while ((l >> 1) - len[l] > (i >> 1) - len[i] && l >= 1 && r <= 2 * n)
len[r++] = len[l--];
len[r] = ((i + 1) >> 1) + len[i] - ((r + 1) >> 1);
i = r - 1;
}
}
int uni[N],ans;
vector<int> vec[N];
int getfa(int pos) {
return pos == uni[pos] ? pos : uni[pos] = getfa(uni[pos]);
}
int main() {
scanf("%d",&n);
scanf("%s",s+1);
manacher();
for (int i = 1 ; i <= n ; ++ i)
r[i] = len[i << 1 | 1];
for (int i = 1 ; i <= n ; ++ i)
uni[i] = i;
for (int i = 1 ; i < n ; ++ i) {
int k = i - (r[i] >> 1);
ans = max(ans,4 * (i - getfa(k)));
vec[i + r[i]].push_back(i);
for (int j = 0 ; j < (int)vec[i].size() ; ++ j)
uni[vec[i][j]] = vec[i][j] + 1;
}
printf("%d\n",ans);
return 0;
}

小结:对一些简单的小技巧还是不熟悉。或许是平庸的大数据结构做多了的问题吧。做题策略要调整。

【做题】BZOJ2342 双倍回文——马拉车&并查集的更多相关文章

  1. 【BZOJ-2342】双倍回文 Manacher + 并查集

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1799  Solved: 671[Submit][Statu ...

  2. BZOJ 2342: [Shoi2011]双倍回文 马拉车算法/并查集

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1123  Solved: 408 题目连接 http://w ...

  3. [BZOJ2342]双倍回文

    对每个大中心暴力找小中心即可. 代码: #include<iostream> #include<cstdio> #include<cstring> #define ...

  4. bzoj千题计划306:bzoj2342: [Shoi2011]双倍回文 (回文自动机)

    https://www.lydsy.com/JudgeOnline/problem.php?id=2342 解法一: 对原串构建回文自动机 抽离fail树,从根开始dfs 设len[x]表示节点x表示 ...

  5. 【BZOJ2342】双倍回文(回文树)

    [BZOJ2342]双倍回文(回文树) 题面 BZOJ 题解 构建出回文树之后 在\(fail\)树上进行\(dp\) 如果一个点代表的回文串长度为\(4\)的倍数 并且存在长度为它的一半的回文后缀 ...

  6. BZOJ2342:[SHOI2011]双倍回文

    浅谈\(Manacher\):https://www.cnblogs.com/AKMer/p/10431603.html 题目传送门:https://www.lydsy.com/JudgeOnline ...

  7. 【洛谷4287】[SHOI2011] 双倍回文(Manacher算法经典题)

    点此看题面 大致题意: 求一个字符串中有多少个长度为偶数的回文串,它的一半也是回文串. \(Manacher\)算法 这应该是\(Manacher\)算法一道比较好的入门题,强烈建议在做这题之前先去学 ...

  8. BZOJ2342 Shoi2011 双倍回文 【Manacher】

    BZOJ2342 Shoi2011 双倍回文 Description Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输 ...

  9. BZOJ2342: [Shoi2011]双倍回文

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 923  Solved: 317[Submit][Status ...

随机推荐

  1. 在caffe-ssd的环境搭建中遇到报错信息:Makefile:588: recipe for target '.build_release/cuda/src/caffe/layers/softmax_loss_layer.o' failed

    错误原因: 1.计算机没有安装GPU 2.有GPU但是NVCCFLAGS设置错误 解决方法: 1.对没有GPU的计算机,需要将Makefile中的CPU之前的#注释去掉,是的caffe运行的处理器进行 ...

  2. Mysql 修改字段长度、修改列名、新增列、修改自增主键起始值

    alter table 表名 modify column 字段名 类型; 例如 数据库中user表 name字段是varchar(30) 可以用 ) ; --修改字段长度 )--修改表列名 ); -- ...

  3. CSS选择符-----元素选择符

       通配选择符(*)           选定所有对象 通配选择符(Universal Selector) 通常不建议使用通配选择符,因为它会遍历并命中文档中所有的元素,出于性能考虑,需酌情使用 & ...

  4. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub

    上篇博文中,我们主要介绍了Azure IoT Hub的基本概念.架构.特性: Azure IoT 技术研究系列1-入门篇 本文中,我们继续深入研究,做一个起步示例程序:模拟设备注册到Azure IoT ...

  5. 【Hadoop学习之四】HDFS HA搭建(QJM)

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 由于NameNode对于整个HDF ...

  6. mysql的sql执行计划详解

    实际项目开发中,由于我们不知道实际查询的时候数据库里发生了什么事情,数据库软件是怎样扫描表.怎样使用索引的,因此,我们能感知到的就只有 sql语句运行的时间,在数据规模不大时,查询是瞬间的,因此,在写 ...

  7. hive 实现一个字段多行转一行 和 一行转多行

    1.多行转一行 多行转一行可以通过concat_ws(',',collect_set(col_name)) as col_new的方式实现,可以参考:https://www.cnblogs.com/s ...

  8. 20165316 预备作业3 Linux安装及学习

    Linux安装 我下载的是VirtualBox 5.2.6和Ubuntu 17.10.1,感觉这两个版本的兼容性不是太好,因为我在Oracle的官网社区中看到不少新版本的问题没有得到解决,而老版本(V ...

  9. 关于Weex你需要知道的一切

    QCon第一天,GMTC全球移动技术大会联席主席.手淘技术老大庄卓然(花名南天)在Keynote上宣布跨平台开发框架Weex开始内测,并将于6月份开源,同时他们也放出官网:http://alibaba ...

  10. createDocumentFragment()用法总结

    1.createDocumentFragment()方法,是用来创建一个虚拟的节点对象,或者说,是用来创建文档碎片节点.它可以包含各种类型的节点,在创建之初是空的. 2.DocumentFragmen ...