您的位置:首页 > 运维架构

HDU 5371 Hotaru's problem Manacher + set维护

2015-08-11 19:32 381 查看
题目大意:

就是现在给出一个长度为N <= 100000的数列, 每个数都是10^9以内的正整数, 现在要在这个数列中找出最长的形似ww^w的串, w^是w反序写出来的串

大致思路:

很常见的一个Manacher + Set维护的类型的题....

首先用Manacher处理出每个位置为中心的回文半径

然后从左往右扫, 每次对于当前位置 i, 其半径覆盖到的最右位置 (i, i + R[i] - 1)添加到set里(作为左中心)

那么对于位置i, 要使其作为右中心的话, 左中心的最右覆盖位置必须能覆盖到这个位置, 于是将set中不能覆盖到这个位置的都删掉

然后查询set中最左边的能够覆盖这个位置的做中心 i', 于是 (i - i')/2就是中间w'的最大长度L, ans就是所有3*L中的最大值, 时间复杂度O(nlogn), n为序列长度

比赛的时候还WA了一次.....ans初始写的-1....真是醉了...

代码如下:

Result  :  Accepted     Memory  :  8380 KB     Time  :  1201 ms

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;

#define maxn 100200
int n;
int in[maxn];
int s[maxn << 1];
int R[maxn << 1];

void Manacher(int *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;
}

set<pair<int, int> > S[2];
set<pair<int, int> > :: iterator it;
int ac = 0;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
ac ++;
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d", &in[i]);
s[0] = -2;
for(int i = 0; i < n; i++)
s[2*i + 1] = -10, s[2*i + 2] = in[i];
s[2*n + 1] = -10;
s[2*n + 2] = -1;
//for(int i = 0; i < 2*n + 3; i++)
//cout<<s[i]<<" ";
//cout<<endl;
Manacher(s, R, 2*n + 2);
// for(int i = 0; i < 2*n +3; i++)
// cout<<R[i]<<endl;
//for(int i = 0; i < 2*n +2 ; i++) cout<<R[i]<<endl;
S[1].clear(); S[0].clear();//S[0] (i + r, i)..., S[1](i, i + r)
int ans = 0;
for(int i = 3; i < 2*n + 1; i += 2)
{
int L = i;
while(!S[0].empty() && (*S[0].begin()).first < L)
{
S[1].erase(make_pair((*S[0].begin()).second, (*S[0].begin()).first));
S[0].erase(S[0].begin());
}
L = i - R[i] + 1;
it = S[1].lower_bound(make_pair(L, 0));
if(it != S[1].end())
{
int now = (*it).first;
ans = max(ans, (i - now) / 2 *3);
}
S[1].insert(make_pair(i, i + R[i] - 1));
S[0].insert(make_pair(i + R[i] - 1, i));
}
printf("Case #%d: %d\n",ac, ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息