~~~题面~~~

题解:

首先有一个直观的想法,如果我们可以求出对于位置i的最长后缀回文串和最长前缀回文串,那么我们枚举分界点然后合并前缀和后缀不就可以得到答案了么?

所以我们的目标就是求出这两个数列,

我们令f[i] 表示以i为结尾的最长回文后缀的长度,g[i]表示以i为开头的最长回文后缀的长度。

由于要找回文串,因此我们先想到manacher。

然后我们可以发现对于这样一个串:

原串:xxxxxxxxxx

新串:#x#x#x#x#x#x#x#x#x#x#

我们可以观察到,假设这时我们已经求出了f和g,那么对于任意位置而言,合并出的最长双回文串中,都是“偶串”,且有一半是'#',一半是原串。

因此我们可以直接合并f[i-1] 和 g[i],并用ans记录最大值,那么这时真正的答案就是ans / 2.

假设我们manacher已经求到了第i位,此时i的最长回文半径是R,且j已经被包括在R里面了,那么显然i对j的贡献是(j - i) * 2 + 1。

而因为贡献只和i与j的位置有关,并且我们的i是从1开始,逐渐递增的,因此对于任意一个j,第一次将它更新的i必然可以产生最优解,因此每个j会且仅会被更新一次。

而被更新的j显然也是递增的,因为如果j后面的k已经被更新的话,说明之前已经有一个i可以使得k被覆盖在内了。那么j既然在k前面,肯定也被覆盖过了,

因此求出f[j]时,j肯定是递增的(也就是说肯定是先求出前面的在求出后面的),因此我们可以直接维护一个指针t(这个指针只是字面上的指针),表示当前已经更新到了t,

一旦被覆盖的MaxRight > t,我们就直接用当前的i来更新t。

对于前缀回文串,我们直接把字符串翻转过来,然后再做一遍相同的操作,再把得到的数组反转回来就可以了

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 202000
/*处理出前缀半径和后缀半径,然后合并。可以发现,在扩充了数列之后(#),
获取的最长双回文串一定是偶串,且# 和 真实字符数量相同。
因此ans就是合并后的最长长度/2*/
int n, pos, maxn, ans;
int f[AC], g[AC], tmp[AC], r[AC];
char s[AC], p[AC]; void pre()//读入
{
scanf("%s", s + );
n = strlen(s + );
for(R i = n; i; --i) s[i * ] = s[i];
n = * n + ;
for(R i = ; i <= n; i += ) s[i] = '#';
for(R i = ; i <= n; i++) p[i] = s[n - i + ];//把原串倒过来做一遍就是后缀了
s[] = p[] = '$', s[n + ] = p[n + ] = '$';
} void build()//处理出前缀半径和后缀半径
{
int t = ;
pos = maxn = ;
for(R i = ; i <= n; i++)
{
r[i] = maxn > i ? min(r[ * pos - i], maxn - i + ) : ;
while(s[i - r[i]] == s[i + r[i]]) ++r[i];
if(i + r[i] - > maxn)
{
maxn = i + r[i] - , pos = i;
if(maxn > t)//更新后缀
{
for(R j = t + ; j <= maxn; j++) f[j] = (j - i) * + ;
t = maxn;
}
}
}
pos = maxn = t = ;
for(R i = ; i <= n; i++)
{
r[i] = maxn > i ? min(r[ * pos - i], maxn - i + ) : ;
while(p[i - r[i]] == p[i + r[i]]) ++r[i];
if(i + r[i] - > maxn)
{
maxn = i + r[i] - , pos = i;
if(maxn > t)//更新后缀
{
for(R j = t + ; j <= maxn; j++) tmp[j] = (j - i) * + ;
t = maxn;
}
}
}
for(R i = ; i <= n; i++) g[i] = tmp[n - i + ];
// for(R i = 1; i <= n; i++) printf("%d ", f[i]);
// printf("\n");
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} void work()//合并
{
for(R i = ; i <= n; i++)
upmax(ans, f[i - ] + g[i]);
printf("%d\n", ans/);
} int main()
{
freopen("in.in", "r", stdin);
pre();
build();
work();
fclose(stdin);
return ;
}

[国家集训队]最长双回文串 manacher的更多相关文章

  1. BZOJ.2565.[国家集训队]最长双回文串(Manacher/回文树)

    BZOJ 洛谷 求给定串的最长双回文串. \(n\leq10^5\). Manacher: 记\(R_i\)表示以\(i\)位置为结尾的最长回文串长度,\(L_i\)表示以\(i\)开头的最长回文串长 ...

  2. luoguP4555 [国家集训队]最长双回文串 manacher算法

    不算很难的一道题吧.... 很容易想到枚举断点,之后需要处理出以$i$为开头的最长回文串的长度和以$i$为结尾的最长回文串的长度 分别记为$L[i]$和$R[i]$ 由于求$R[i]$相当于把$L[i ...

  3. 洛谷P4555 [国家集训队]最长双回文串(manacher 线段树)

    题意 题目链接 Sol 我的做法比较naive..首先manacher预处理出以每个位置为中心的回文串的长度.然后枚举一个中间位置,现在要考虑的就是能覆盖到i - 1的回文串中 中心最靠左的,和能覆盖 ...

  4. P4555 [国家集训队]最长双回文串

    P4555 [国家集训队]最长双回文串 manacher 用manacher在处理时顺便把以某点开头/结尾的最长回文串的长度也处理掉. 然后枚举. #include<iostream> # ...

  5. 洛谷 P4555 [国家集训队]最长双回文串 解题报告

    P4555 [国家集训队]最长双回文串 题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为\(n\)的串 ...

  6. Manacher || P4555 [国家集训队]最长双回文串 || BZOJ 2565: 最长双回文串

    题面:P4555 [国家集训队]最长双回文串 题解:就.就考察马拉车的理解 在原始马拉车的基础上多维护个P[i].Q[i]数组,分别表示以i结尾最长回文子串的长度和以i开头的最长回文子串的长度 然后就 ...

  7. 【洛谷】P4555 [国家集训队]最长双回文串

    P4555 [国家集训队]最长双回文串 题源:https://www.luogu.com.cn/problem/P4555 原理:Manacher 还真比KMP好理解 解决最长回文串问题 转化为长度为 ...

  8. Manacher【p4555】 [国家集训队]最长双回文串

    题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为 n 的串 S ,求 S 的最长双回文子串 T ,即可 ...

  9. P4555 [国家集训队]最长双回文串(回文树)

    题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为 n 的串 S ,求 S 的最长双回文子串 T ,即可 ...

随机推荐

  1. typescript语法

    先来讲一讲TypeScript出现的背景 前端javascript的编程思想与后端java面向对象的编程思想有很大的不同,微软公司借鉴了coffeescript语言,继承了很多C#和java的编程思想 ...

  2. hdu2509Be the Winner(反nim博弈)

    Be the Winner Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  3. Python全栈 正则表达式(re模块正则接口全方位详解)

    re模块是Python的标准库模块 模块正则接口的整体模式 re.compile 返回regetx对象 finditer fullmatch match search 返回 match对象 match ...

  4. 在github上面创建属于自己的个性主页

    圈子里面越来越多的同事在github上面创建自己的项目文档,那里确实高手云集,海内外的技术大牛小牛们都在那儿有一席之地,为“helloword”贡献自己. 以上感慨略过... 这几日正想创建一个自己的 ...

  5. Memcache的客户端连接系列(四) PHP

    关键词: Memcached   PHP 客户端 声明:本文并非原创,转自华为云帮助中心的分布式缓存服务(Memcached)的用户指南.客户端连接方法通用,故摘抄过来分享给大家. PHP客户端 Re ...

  6. centos7安装zabbix3.2详解

    服务器端安装 1.安装仓库 rpm -ivh http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/zabbix-release-3.2-1.el7.noar ...

  7. 【未完】训练赛20190304:KMP+树状数组+线段树+优先队列

    头炸了啊,只做出L题,前两天刚看的Shawn zhou的博客学习的,幸亏看了啊,否则就爆零了,发现题目都是经典题,线段树,KMP,我都没看过,最近又在复习考研,真后悔大一大二没好好学习啊,得抽时间好好 ...

  8. LeetCode 100——相同的树

    1. 题目 2. 解答 针对两棵树的根节点,有下列四种情况: p 和 q 都为空,两棵树相同: p 不为空 q 为空,两棵树不相同: p 为空 q 不为空,两棵树不相同: p 和 q 都不为空,如果两 ...

  9. 线性代数之——A 的 LU 分解

    1. A = LU 之前在消元的过程中,我们看到可以将矩阵 \(A\) 变成一个上三角矩阵 \(U\),\(U\) 的对角线上就是主元.下面我们将这个过程反过来,通一个下三角矩阵 \(L\) 我们可以 ...

  10. Python3 小工具-僵尸扫描

    僵尸机的条件: 1.足够闲置,不与其他机器进行通讯 2.IPID必须是递增的,不然无法判断端口是否开放 本实验僵尸机选择的是Windows2003 from scapy.all import * im ...