BZOJ 2565 Mancher 算法求 最长双回文串
来源:互联网 发布:约翰威廉姆斯配乐知乎 编辑:程序博客网 时间:2024/06/06 10:02
http://www.lydsy.com/JudgeOnline/problem.php?id=2565
求出最长的子串可以分成两个回文串
先处理出以每个位置为中心的最长回文子串,然后我是求了两个这样的数组left[] right[],分别表示某位置往左最长的回文子串(以该位置结尾),右边的雷同
需要线性扫两遍。。。
处理这两个数组的时候细节问题整了半天,所幸最后还是整出来了。
#include<cstdio>#include<cstring>#include<vector>#include<algorithm>using namespace std;const int maxn= 200010;namespace M {int n;struct node {int a,b;int cen;node() {}node(int _a,int _b):a(_a),b(_b){};bool operator < (const node&cmp) const {return b < cmp.b;}}in[maxn];vector<pair<int,int> > P[maxn] ;///P[i]记录以i为中心的所有的最长回文子串(其实最多只有两个,奇偶性。。) int left[maxn] , right[maxn];bool ji[maxn];void solve(){memset(ji,false,sizeof(ji));int mx = 0;for(int i = 0; i < n; i++)mx = max(mx,in[i].b);for(int i = 1; i <= mx; i++) P[i].clear();for(int i = 0; i < n; i++){in[i].cen= in[i].a+in[i].b >> 1;P[in[i].cen].push_back(make_pair(in[i].a,in[i].b));} int pt = 1; for(int i = 1; i <= mx; i++) { for(; pt < i; pt++) { int a = P[pt][0].first; int b = P[pt][0].second; if(b>=i) { ji[i] = true; break;}if(P[pt].size()==1) continue;a = P[pt][1].first;b = P[pt][1].second;if(b>=i){break;}}left[i] = pt;}for(int i = 1; i <= mx; i++){left[i] = max(1,(i - left[i])*2+ji[i]);}pt = mx;memset(ji,false,sizeof(ji));for(int i = mx; i >= 1; i--){right[i] = i; for(; pt >= i; pt--) { int a, b; if(P[pt].size() > 1) { a = P[pt][1].first; b = P[pt][1].second; if(a<=i) { right[i] = pt + 1; break; } } a = P[pt][0].first; b = P[pt][0].second; if(a<=i) {right[i] = pt; ji[i] = true; break;}}}for(int i = 1; i <= mx; i++){right[i] = max(1,(right[i] - i)*2+ji[i]);} int ans = 0;for(int i = 1; i < mx; i++){ ans = max(ans,left[i]+right[i+1]);}printf("%d\n",ans);}}struct Mancher {char str[maxn];//start from index 1int p[maxn];char s[maxn];int n;void checkmax(int &ans,int b){if(b>ans) ans=b;}inline int min(int a,int b){return a<b?a:b;}void kp(){int i;int mx = 0;int id;for(i=1; i<n; i++){if( mx > i )p[i] = min( p[2*id-i], p[id]+id-i );elsep[i] = 1;for(; str[i+p[i]] == str[i-p[i]]; p[i]++) ;if( p[i] + i > mx ) {mx = p[i] + i;id = i;}}}void pre(){int i,j,k;n = strlen(s);str[0] = '$';str[1] = '#';for(i=0;i<n;i++){str[i*2 + 2] = s[i];str[i*2 + 3] = '#';}n = n*2 + 2;str[n] = 0;}void solve() // 求出所有的最长回文子串所在的区间{int & tot = M::n;tot = 0;for(int i = 2; i < n; i++){if(i%2&&p[i]==1) continue;if(i%2){M::in[tot++] = M::node(i/2-p[i]/2+1,i/2+p[i]/2);//printf("%d %d\n",i/2-p[i]/2+1,i/2+p[i]/2);}else {M::in[tot++] = M::node(i/2-(p[i]/2-1),i/2+(p[i]/2-1));//printf("%d %d\n",i/2-(p[i]/2-1),i/2+(p[i]/2-1));}}}}task1;int main(){while( scanf("%s", task1.s) !=EOF ){task1.pre();task1.kp();task1.solve();M::solve();}return 0;}
- BZOJ 2565 Mancher 算法求 最长双回文串
- 最长回文字串(mancher算法)
- poj 3974 Palindrome 裸的最长回文子串Mancher算法O(n)
- BZOJ 2565 最长双回文串 Manacher
- [bzoj 2565] 最长双回文串
- BZOJ 2565 最长双回文串(manacher)
- BZOJ 2565: 最长双回文串
- BZOJ 2565 最长双回文串
- BZOJ 2565 最长双回文串
- bzoj 2565: 最长双回文串 manacher
- BZOJ 2565 最长双回文串 Manacher
- BZOJ 2565: 最长双回文串 manacher
- bzoj 2565: 最长双回文串
- bzoj 2565 最长双回文串 manacher
- BZOJ 2565: 最长双回文串 manacher
- bzoj 2565: 最长双回文串 manachar
- BZOJ 2565 最长双回文串
- bzoj 2565: 最长双回文串 manacher
- STM32F10x 学习笔记3(CRC计算单元)
- hdoj 2084 数塔
- 正则表达式
- leetcode 125: Restore IP Addresses (uncompleted)
- C++简述
- BZOJ 2565 Mancher 算法求 最长双回文串
- 驱动模块和桩模块
- 查询的发生过程!解剖group by where having的用法!+面试题
- MyEclipse8.5优化
- cocos2d-x 图片平铺
- VC中的CEDIT class 自动滚动到最后一行
- 我的程序员之路(2)----关于好心朋友的评论让我有压力
- get cpu information by standard modules
- struts2 的action的生命周期