BZOJ 2342 [Shoi2011] 双倍回文 Manacher + set维护
来源:互联网 发布:统计联网直报平台数据 编辑:程序博客网 时间:2024/05/17 03:03
题目大意:
就是现在给出一个长度为n的字符串(1 <= 2*10^5), 求最长双倍回文字串T的长度 (T是最长双倍回文字串当且仅当 T的长度是4的倍数且T是回文串, 其左半部分和右半部分都是回文串)
大致思路:
首先用manacher处理处所有字符为中心的回文半径, 然后用set维护对于每个正中心的位置查询左中心的位置即可 (论文题)
细节写在代码注释里了
代码如下:
Result : Accepted Memory : 18264 KB Time : 748 ms
/************************************************************** Problem: 2342 User: Gatevin Language: C++ Result: Accepted Time:748 ms Memory:18264 kb****************************************************************/ /* * Author: Gatevin * Created Time: 2015/3/24 10:09:54 * File Name: Chitoge_Kirisaki.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;/* * 首先可以Manacher处理出所有中心的回文半径 * 然后枚举双倍回文的正中心的位置, 当然这个位置必须是'#' * 然后对于这样一个回文串, 要使得其实双倍回文, 在左边必须存在左中心j * 显然要满足的条件有j位置也是'#', 然后 (i - j)*2 - 1 + 1 <= R[i] * 所以左中心一定在[i - R[i]/2, i)之间为'#'的位置 * 那么要做的就是在这个区间当中找到最小的回文半径能覆盖到正中心i的那个 * 可以使用一个set来维护可能的'#'位置, 如果当以i为正中心, j为左中心不能覆盖到i * 那么j也就不能覆盖到比i更右边的正中心了, 可以从set中删去j, 节省查询时间 * 这样集合当中的元素最多被删除n次, 时间复杂度O(nlogn) * 觉得有点不好说但是发现 n <= 2*10^5还是过了.. */#define maxn 1000100 int n;char in[maxn >> 1], s[maxn];int R[maxn];set<int> S; void Manacher(char *s, int *R, int n){ int p = 0, mx = 0; R[0] = 1; for(int i = 1; i <= n; i++) { if(mx > i) R[i] = min(R[2*p - i], mx - i); else R[i] = 1; while(s[i - R[i]] == s[i + R[i]]) R[i]++; if(i + R[i] > mx) mx = i + R[i], p = i; } return;} int main(){ scanf("%d", &n); scanf("%s", in); s[0] = '@'; for(int i = 0; i < n; i++) s[2*i + 1] = in[i], s[2*i + 2] = '#'; s[2*n] = '$'; Manacher(s, R, 2*n); for(int i = 2; i <= 2*n - 4; i+= 2) S.insert(i); int ans = 0; for(int i = 4; i <= 2*n - 4; i += 2)//枚举可能是中心的'#' { int l = i - (R[i] >> 1); if(l & 1) l++; while(l != i) { if(l + R[l] >= i) { ans = max(ans, (i - l) << 1); break; } else S.erase(l), l = *S.upper_bound(l); } } printf("%d\n", ans); return 0;}
0 0
- BZOJ 2342 [Shoi2011] 双倍回文 Manacher + set维护
- BZOJ 2342([Shoi2011]双倍回文-manacher+set)
- BZOJ 2342: [Shoi2011]双倍回文 (Manacher+set)
- 【BZOJ】2342 [Shoi2011]双倍回文 manacher+set
- bzoj 2342: [Shoi2011]双倍回文(manacher)
- BZOJ 2342 [Shoi2011]双倍回文 Manacher
- [BZOJ]2342: [Shoi2011]双倍回文 manacher
- BZOJ 2342: [Shoi2011]双倍回文 manacher
- 【bzoj2342】 SHOI2011 双倍回文 manacher+set
- bzoj2342 [Shoi2011]双倍回文(manacher+暴力/set)
- bzoj 2342: [Shoi2011]双倍回文
- BZOJ 2342 [Shoi2011]双倍回文
- BZOJ 2342: [Shoi2011]双倍回文
- bzoj 2342: [Shoi2011]双倍回文
- BZOJ2342: [Shoi2011]双倍回文【Manacher】
- [bzoj2342][Shoi2011]双倍回文 manacher
- 【BZOJ2342】【Shoi2011】双倍回文 Manacher算法
- [BZOJ2342][Shoi2011]双倍回文(manacher)
- MySQL 的唯一索引
- SpringMVC+Spring3+Hibernate Quartz定时任务调用service查询获取不到CurrentSession
- IOS APPstore发布
- 十个最火的HTML5框架与移动应用框架的比较
- 重载函数的重载确定过程
- BZOJ 2342 [Shoi2011] 双倍回文 Manacher + set维护
- myEclipse8.5 破解方法
- &引用和&取地址
- COPY innodb存储引擎索引概述
- 为啥要重写equals()和hashcode()方法
- C#中如何操作XML,对XML进行增、删、改节点
- 一道javaBean内省题
- 采购订单邮件发送预警设置
- C语言_辗转相除法求最大公约数