COI2016 Palinilap(manacher+后缀数组)

博客探讨了一道题目,要求通过修改字符串中的一个字符,最大化所有不同回文串的长度之和。文章指出,使用Manacher算法计算半径数组是解决问题的关键,但可能比二分查找加哈希更复杂。文章讨论了修改字符如何影响回文串,包括破坏现有回文串和创建新回文串的情况,并提出了利用线段树、前缀和以及LCP(最长公共前后缀)的方法来处理这些变化。
摘要由CSDN通过智能技术生成

题意:给出一个小写字母组成的字符串,修改一个字符(或者不改),使得字符串中所有回文串的长度之和最大(本质相同的回文串算多个)。

好神的题。。题意简单易懂但是做起来非常麻烦。。

以后如果只是求求lcp之类的最好写二分+hash,写个后缀数组简直是自讨苦吃。。

很显然回文串的长度之和就是manacher算法中半径数组之和。

修改一个字符有可能破坏一些回文串,也有可能引入一些新的回文串,只要我们能对每个字符处理出这两个值即可。

先考虑破坏的。考虑一个点,以它为中心扩展出的极大回文串内如果有字母被修改,显然会损失这个点的半径值,且损失程度为从中间向两边递减的公差为1的等差数列。可以用线段树来加,也可以离线+前缀和。

再考虑增加的。对一个点而言,记l和r分别为这个点所能扩展的极大回文串的左右端点。如果l=1或者r=n,则显然这个点半径值无论如何也不能增大了。否则要让这个点的半径值增大,就必须将s[l-1]改为s[r+1]或者将s[r+1]改为s[l-1],修改之后这个点的半径值就可以增加s[r+1]向右和s[l-1]向左所能匹配的最大长度。这个可以将原串逆序后放在后面求一次后缀数组之和用lcp来实现。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL long long
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const double alp = 0.75;
const LL INF = 1ll<<61;
const int MAXN &
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值