[SHOI2011]双倍回文 题解

看了一些写回文自动机的大佬的代码,我深感敬畏,于是我转身向Manacher走去

现在荣登最优解第一页……

说实话,这个方法的复杂度是很玄学的,但是加了一些优化之后,就几乎不可能被卡到 \(O(n^2)\) 了。

具体思路如下:

预处理字符串部分就略过吧

  • 我们预先跑一次 Manacher 算法,考虑到我们其实只需要偶数的回文串的信息,所以将步长设为 2 就行了。
int M(0), R(0), p;
for (int i(1); i < n; i += 2) {
p = R > i ? min(R - i + 1, P[(M<<1) - i]) : 1;
while (s[i + p] == s[i - p]) ++p; // 向两边扩展
if (i + p - 1 > R) M = i, R = i + p - 1; // 更新边界
P[i] = p;
}
  • 接着,我们寻找答案。考虑枚举每一个以 i 为中心的偶数回文串。对于这个回文串,我们枚举其回文左区间内的所有点,判断其能否与右区间内对应的区间构成双倍回文即可。换句话来说,假如我们枚举到了 j,那么如果 j 是左侧的合法答案,就一定有 j + P[j] > i

    额,注意一下,这里的 P[i] 指的是回文串的直径,是包括了中间点的元素的。也就是说,回文串所在区间其实是 (i - P[i], i + P[i])(闭区间!)

    但是,这并不是充要条件。我们考虑这样一种情况

    这个时候,j 其实是不合法的,因为绿色的区间才是合法的区间(合法的区间一定是被 i 的回文区间完全包含的!)。所以,对于合法区间的中点,一定在 i 的做右区间中点的左边或者右边。那么实际上,我们只需要枚举 (i, i + P[i]/2] 作为中点即可。

  • 小小的优化:我们需要最大值,所以令答案为 ans,我们枚举 (i + ans, i + P[i]/2] 即可。而且,我们需要的偶数的回文串,所以步长也可以设为 2 来枚举的。

参考代码:

#include <stdio.h>

#define N 1000006

int n, P[N];
char s[N]; inline int min(int x, int y) {
return x < y ? x : y;
}
inline int max(int x, int y) {
return x > y ? x : y;
} int main() {
scanf("%d", &n); char tmp;
do tmp = getchar(); while (tmp < 'a');
s[0] = '^', s[1] = '#', s[2] = tmp, s[3] = '#';
for (int i(2); i <= n; ++i) {
s[(i<<1)] = getchar(), s[(i<<1)|1] = '#';
} // printf("%s\n", s); int ans(0);
int M(0), R(0), p;
n = (n<<1) + 2;
for (int i(1); i < n; i += 2) {
p = R > i ? min(R - i + 1, P[(M<<1) - i]) : 1;
while (s[i + p] == s[i - p]) ++p; // 向两边扩展
if (i + p - 1 > R) M = i, R = i + p - 1; // 更新边界
P[i] = p;
}
// 寻找答案
for (int i(1); i < n; i += 2) {
int p = P[i] / 2 + 1;
for (int r(ans); r < p; r += 2) {
if (P[i + r] > r && P[i - r] > r) ans = r;
}
}
printf("%d\n", ans + ans);
return 0;
}

[SHOI2011]双倍回文 题解的更多相关文章

  1. 洛谷 P4287 [SHOI2011]双倍回文题解

    前言 用了一种很奇怪的方法来解,即二分判断回文,再进行某些奇怪的优化.因为这个方法很奇怪,所以希望如果有问题能够 hack 一下. 题解 我们发现,这题中要求的是字符串 \(SS'SS'\),其中 \ ...

  2. [SHOI2011]双倍回文 manacher

    题面: 洛谷:[SHOI2011]双倍回文‘ 题解: 首先有一个性质,本质不同的回文串最多O(n)个. 所以我们可以对于每个i,求出以这个i为结尾的最长回文串,然后以此作为长串,并判断把这个长串从中间 ...

  3. Manacher || BZOJ 2342: [Shoi2011]双倍回文 || Luogu P4287 [SHOI2011]双倍回文

    题面:[SHOI2011]双倍回文 题解:具体实现时,就是在更新mr时维护前半段是回文串的最长回文串就好了 正确性的话,因为到i时如果i+RL[i]-1<=mr,那么答案肯定在i之前就维护过了: ...

  4. BZOJ2342: [Shoi2011]双倍回文

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

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

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

  6. 2018.06.30 BZOJ 2342: [Shoi2011]双倍回文(manacher)

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符串 ...

  7. bzoj 2342: [Shoi2011]双倍回文 -- manacher

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符 ...

  8. BZOJ2342 Shoi2011 双倍回文 【Manacher】

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

  9. BZOJ 2342 [Shoi2011]双倍回文(manacher+并查集)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2342 [题目大意] 记Wr为W串的倒置,求最长的形如WWrWWr的串的长度. [题解] ...

  10. BZOJ2342:[SHOI2011]双倍回文

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

随机推荐

  1. Redis基础(一)——字符串、hash类型的基本使用

    day09--Redis Redis介绍和安装 # Redis:软件,存储数据的,速度非常快,Redis是一个key-value存储系统(没有表的概念),cs架构的软件 服务端 客户端(python作 ...

  2. 如何使用XSSFWorkbook读取文本薄?

    [版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18146625 出自[进步*于辰的博客] 1.文件兼容类 ...

  3. vue 弹出框挂载富文本,富文本()无法实例化问题

    因为elementUI的dialog组件,他是v-if渲染,再页面刚加载时,这个弹出框还未进行挂载,我们就让他v-show显示. ,富文本实例再mounted里面挂载即可

  4. maven BUILD FAILURE

    maven BUILD FAILURE 使用命令进行导包失败,错误为BUILD FAILURE 然后使用mvn help:system看一下是不是maven有问提 然后出现了新的错误No plugin ...

  5. 力扣485(java)-最大连续数1的个数(简单)

    题目: 给定一个二进制数组, 计算其中最大连续 1 的个数. 示例: 输入:[1,1,0,1,1,1]输出:3解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3. 提示: 输入 ...

  6. Serverless 场景排查问题利器 : 函数实例命令行操作

    ​简介:实例命令行功能的推出希望能消除用户使用 Serverless 的"最后一公里",直接将真实的函数运行环境展现给用户. 背景介绍 全托管的 Serverless 计算平台能给 ...

  7. [Trading] 日间交易中的成交量分析 - 使用成交量趋势来提高你的效果

    在交易中,成交量代表在特定时期内股票或期货合约的易手单位数量. 交易员将其作为一个关键指标,因为它让他们知道资产的流动性水平,以及他们在接近当前价格的情况下买入或卖出头寸的容易程度,这可能是一个移动的 ...

  8. dotnet OpenXML 聊聊文本段落对齐方式

    本文来和大家聊聊在 OpenXML 里面,文本段落对齐方式.在 Word 和 PPT 的文本段落对齐规则是相同的,对齐的规则比较多,本文将一一告诉大家 文本的段落对齐,需要设置给段落属性上,在 Ope ...

  9. C++多态与虚拟:C++编译器对函数名的改编(Name Mangling)

    如果函数名称都相同(也就是被overloaded),编译器在面对你的函数唤起动作时,究竟是如何确定调用哪个函数实体呢?事实上,编译器把所有同名的overloaded functions视为不同的函数, ...

  10. FPGA最大工作频率教程

    FPGA最大工作频率教程 1.  Quartus的时序分析 作为编译过程的一部分,Quartus对布局布线的电路做时序分析.在编译报告里,展开"Timing Analyzer",这 ...