洛谷P4555 [国家集训队] 最长双回文串
[国家集训队]最长双回文串
题目描述#
顺序和逆序读起来完全一样的串叫做回文串。比如acbca
是回文串,而abc
不是(abc
的顺序为abc
,逆序为cba
,不相同)。
输入长度为的串,求的最长双回文子串,即可将分为两部分,,()且和都是回文串。
输入格式#
一行由小写英文字母组成的字符串。
输出格式#
一行一个整数,表示最长双回文子串的长度。
样例 #1#
样例输入 #1#
baacaabbacabb
样例输出 #1#
12
提示#
【样例说明】
从第二个字符开始的字符串aacaabbacabb
可分为aacaa
与bbacabb
两部分,且两者都是回文串。
对于100%的数据,
2018.12.10、2018.12.15 感谢 @Ycrpro 提供 hack 数据两组
SOLUTION#
题意为求出 的一个子串 ,并且 可以分为两个非空的回文串。
对于回文串,我们一般考虑 马拉车(manacher) 来解决,对于本题,考虑分为两个非空的回文串,那么间隔点一定是 # ,那么我们可以维护出每个位置的回文半径 的同时,可以维护以每个最长回文子串的左端点和右端点,然后分别记录出以他们为起点和终点的最长回文子串的长度 ,然后考虑维护以每个 # 为起点或者终点的最长回文串的长度,由于我们只需要 # 位置的信息,并且在 马拉车 的过程中已经求得了以某个点起点或者终点得最长的回文串的长度,那么对于以某个位置 为起点的最长回文串的长度就是以 为起点的最长回文串的长度再减去 , 终点同理,最终枚举 # 求答案即可。
CODE#
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 3E5 + 10;
int n, m, Case;
char s[N], str[N];
int p[N], Left[N], Right[N];
template <typename T> void chkmax(T &x, T y) { x = max(x, y); }
template <typename T> void chkmin(T &x, T y) { x = min(x, y); }
void manacher() {
int rt = 0, mid = 0;
for(int i = 1; i <= m; i ++ ) {
p[i] = i < rt ? min(p[2 * mid - i], rt - i) : 1;
while(str[i + p[i]] == str[i - p[i]]) ++ p[i];
if(i + p[i] > rt) {
rt = i + p[i];
mid = i;
}
chkmax(Left[i + p[i] - 1], p[i] - 1);
chkmax(Right[i - p[i] + 1], p[i] - 1);
}
}
int main() {
str[0] = '!', str[1] = '#';
scanf("%s", s);
n = strlen(s);
for(int i = 0; i < n; i ++ ) {
str[i * 2 + 2] = s[i];
str[i * 2 + 3] = '#';
}
m = n * 2 + 1;
str[m + 1] = '@';
manacher();
for (int i = 1; i <= m; i += 2) chkmax(Right[i], Right[i - 2] - 2);
for (int i = m; i >= 1; i -= 2) chkmax(Left[i], Left[i + 2] - 2);
int ans = 0;
for (int i = 1; i <= m; i += 2) if (Left[i] && Right[i]) {
chkmax(ans, Left[i] + Right[i]);
}
cout << ans << "\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现