SHTSC2011(SHOI) 双倍回文 一道用Manacher优化的动态维护题
2016-04-11 20:54
429 查看
题目大意
给你一个长度为NN的字符串,求它的最长双倍回文字串。双倍回文字串:记xx倒置的串为xRx^R,而双倍回文串是能表示成x+xR+xR+xx + x^R + x^R +x形式的字符串。
N≤500000N \leq 500000
解题思路
根据双倍回文串的可知它的长度一定是4的倍数,且由两个相同的有偶数个字符的回文串构成,我们可以先用Manacher与预处理出每一个位置的最长回文半径RiR_i。那么我们设这个串的对称轴是在第pp个字符和第p+1p + 1个字符之间(即pp为第一个xRx^R结尾的位置),qq为第二个xRx^R结尾的位置。那么为了满足双倍回文串的定义q−Rq<=pq - R_q <= p且q<=p+Rp/2q <= p + R_p / 2(这个画一画就能看出来)即只要满足这个条件的一对p,p, qq就可以更新答案。我们把q−Rqq - R_q排个序,我们在枚举pp时就维护满足条件一qq,把它们加入队列。由于pp递增,所以加到队列的qq就不会出队了。因为答案等于len(p,q)∗4len(p,q) * 4,所以我们只要在队列中找到p+Rp/2p + R_p / 2前面的第一个点就可以了找到对于当前pp的最优解。这里可以用STL维护,也可以用并查集维护。
程序
这个代码为了简洁,用了STL库,跑的有点慢,跑全是aa的极限数据可能会被卡。其实维护前面的第一个点可以用并查集来维护。//SHTSC2011 Double Palindrome String YxuanwKeith #include <cstring> #include <cstdio> #include <algorithm> #include <set> using namespace std; const int MAXN = 5e5 + 5; set<int> D; char S[MAXN]; int N, R[MAXN], Ord[MAXN]; bool cmp(int a, int b) { return a - R[a] < b - R[b];} void Manacher() { int Max = 0, Id; for (int i = 1; i <= N; i ++) { R[i] = (Max >= i) ? min(Max - i, R[2 * Id - 1]) : 0; for (; S[i + R[i] + 1] == S[i - R[i]]; R[i] ++); if (R[i] + i > Max) Max = R[i] + i, Id = i; } } void Prepare() { Manacher(); for (int i = 1; i <= N; i ++) Ord[i] = i; sort(Ord + 1, Ord + 1 + N, cmp); } void Solve() { int Last = 0, Ans = 0; for (int i = 1; i <= N; i ++) { while (Last <= N && Ord[Last] - R[Ord[Last]] <= i) D.insert(Ord[Last ++]); set<int> :: iterator Side = D.upper_bound(i + R[i] / 2); if (Side == D.begin()) continue; Ans = max(Ans, *(--Side) - i); } printf("%d", Ans * 4); } bool Check() { for (int i = 2; i <= N; i ++) if (S[i] != S[i - 1]) return 0; printf("%d", N / 4 * 4); return 1; } int main() { scanf("%d", &N); scanf("%s", S + 1); if (Check()) return 0; Prepare(); Solve(); }
相关文章推荐
- Centos7 ssh修改默认端口号
- 【 OpenCV学习笔记 002】OpenCV 2.4.9组件结构解析
- 在VS2013中配置OpenCL开发 环境
- 嵌入式Linux中常见的问题
- OpenCV中贝叶斯分类器相关的API及其用法
- opencv 鼠标操作SetMouseCallback()函数传递用户定义参数的问题
- hadoop开发环境搭建
- 山东省第一届ACM省赛 D SDUT 2154 Shopping
- 每天一个linux命令(1):pwd命令
- linux下的ssh服务
- Linux目录结构及文件基础操作
- linux模块的编译步骤详解
- 每天一个Linux命令目录
- Centos6.5 ssh修改默认端口号
- Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择
- 近 100 个 Linux 常用命令大全
- linux 安装jdk
- Linux基础篇一
- linux下, 使用iconv命令实现文件目录编码批量转换
- 堆与堆排序与topK问题