利用Manacher求出每两个数字中间位置的回文长度
之后利用set进行维护,大题思路如下:
要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,比如上边的两个字符串,共享 8 9 10这一部分。 也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样。 因为我们已经记录下来以第i个点和第i+1个点为中心的回文串长度, 那么问题可以转化成,相距x的两个数a[i],a[i+x],满足a[i]/2>=x 并且 a[i+x]/2>=x,要求x尽量大
这可以用一个set维护,一开始集合为空,依次取出a数组中最大的元素,将其下标放入set中,每取出一个元素,再该集合中二分查找比i+a[i]/2小,但最大的元素,更新答案。 然后查找集合中比i-a[i]/2大,但最小的元素,更新答案。
参考官方题解:http://bestcoder.hdu.edu.cn/blog/
代码如下:
#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100005;
int Ma[maxn * 2],Mp[maxn * 2];
int arr[maxn],len,n;
set<int>st;
set<int>::iterator it;
struct Node{
int id,val;
}node[maxn * 2];
int cmp(Node p,Node q){
return p.val > q.val;
}
int read(){
char z=getchar();
while(z <'0'|| z>'9') z = getchar();
int ans=0;
while(z>='0' && z<='9') {
ans=ans * 10 + z - '0';
z = getchar();
}
return ans;
}
//Manacher
void Manacher(){
int l = 0;
Ma[l++] = -2;
Ma[l++] = -1;
for(int i = 1; i <= n; i++){
Ma[l++] = arr[i];
Ma[l++] = -1;
}
int mx = 0,id = 0;
len = l;
for(int i = 0; i < l; i++){
Mp[i] = mx > i ? min(Mp[2 * id - i],mx - i) : 1;
while(Ma[i + Mp[i]] == Ma[i - Mp[i]]) Mp[i] ++;
if(i + Mp[i] > mx){
mx = i + Mp[i];
id = i;
}
}
}
//debug
void debug(){
for(int i = 0; i < len; i++)
printf("%2d ",i);
puts("");
for(int i = 0; i < len; i++)
printf("%2d ",Ma[i]);
puts("");
for(int i = 0; i < len; i++)
printf("%2d ",Mp[i]);
puts("");
}
//main
int main(){
int T,Case = 1;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(Mp,0,sizeof(Mp));
for(int i = 1; i <= n; i++)
arr[i] = read();
Manacher();
//debug();
st.clear();
for(int i = 1; i <= n; i++){
node[i].id = i;
node[i].val = (Mp[i * 2 + 1] - 1) / 2;
}
sort(node + 1,node + n + 1,cmp);
int ans = 0;
for(int i = 1; i <= n; i++){
int _find1 = node[i].id - node[i].val;
int _find2 = node[i].id + node[i].val;
//printf("%d %d\n",node[i].id,node[i].val);
st.insert(node[i].id);
it = st.lower_bound(_find1);
ans = max(ans,node[i].id - *it);
it = st.upper_bound(_find2);
it --;
ans = max(ans,*it - node[i].id);
}
printf("Case #%d: %d\n",Case++,ans * 3);
}
return 0;
}