题意:
假设对于字符串A,它的反串为A'。
给出一个字符串,找出形式为AA'A的最长串的长度。
思路:
先用manacher跑一边,得到对于每一个位置i,以i为中心回文串的长度Mp[i]
以回文串AA'的中心i1为圆心,以AA'的半径Mp[i1]为半径,做圆O1
以回文串A'A的中心i2为圆心,以A'A的半径Mp[i2]为半径,做圆O2
若要满足连续的AA'A
必有:
i1在圆O2上或在圆O2内
i2在圆O1上或在圆O1内
那么问题转化为在一根最长为1e5的数轴上,有若干个圆,寻找满足条件的圆心距最大的一对圆。最长串的长度就等于3/2倍圆心距。
分析转化后的问题:
对于一个圆,如果他是满足条件的一对圆中左边的圆,那么这一对圆中右边的圆的最左端x必有x<=i。
即对于每一个圆心为i左边的圆,满足最大圆心距的右边的圆为,所有满足最左端x<=i的圆中,圆心最大的那个圆。
由此,我们可以使用线段树解决这个问题。
记录下所有圆的左端点,同时附上圆的圆心。按左端点从小到大排序。对于每个圆心为i的圆,查询左端点在[1,i]上左圆能覆盖最大的圆心。
共n个圆,每次查询的效率为logn。总的时间复杂度为O(nlogn)
代码:(904MS)
#include <bits/stdc++.h>
using namespace std;
#define ls rt<<1,l,mid
#define rs (rt<<1)|1,mid+1,r
#define mi (l+r)>>1
const int INF=0x3f3f3f3f;
const int MAXN=100100;
typedef struct Node{
int x;int y;
bool operator < (const Node &a)const{
if(a.x==x)
return a.y>y;
return a.x>x;
}
}Node;
int Ma[MAXN*2];
int Mp[MAXN*2];
int Mx[MAXN*2];
int len;
int v;
int st,en;
int prenum;
Node lp[MAXN*2];
Node pre[MAXN*2];
int maxn[MAXN*3];
int cut;
int ll;
int ans;
int pp;
Node t;
int k;
int T,n;
int buf[MAXN];
int query(int rt,int l,int r){
if(maxn[rt]-k<=ans) return -INF;//剪枝,如果区间上最大圆心距不大于现有答案,则返回
int mid=mi;
if(st<=l&&r<=en){
if(maxn[rt]<=v)//判断左圆是否能覆盖
return maxn[rt];
else{
if(l==r)
return -INF;
else
return max(query(rs),query(ls));
}
}
int ansk=-INF;
if(st<=mid)
ansk=max(ans,query(ls));
if(mid<en)
ansk=max(ans,query(rs));
return ansk;
}
void build(int rt,int l,int r){
if(l==r){
maxn[rt]=lp[pp].y;
pp++;
return ;
}
int mid=mi;
build(ls);
build(rs);
maxn[rt]=max(maxn[rt<<1],maxn[(rt<<1)|1]);
return ;
}
int manachar(){
ll=0;ans=0;
len=n;
Ma[ll++]=-2;
Ma[ll++]=-1;
prenum=0;
for(int i=0; i<len; i++){
Ma[ll++]=buf[i];
Ma[ll++]=-1;
}
Ma[ll]=-3;
int mx=0,id=0;cut=0;
for(int i=0; i<ll; 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;
}
Mx[i]=mx;
if(Mp[i]>2){//当Mp[i]<=2时,说明回文串就是一个单字符,没有作为圆的必要。
pre[prenum].x=Mp[i];
pre[prenum].y=i;
prenum++;
lp[cut].x=i-Mp[i]+1;
lp[cut].y=i;
cut++;
}
}
if(cut>1){
memset(maxn,0,sizeof(maxn));
sort(lp,lp+cut);
sort(pre,pre+prenum);
pp=0;
build(1,1,cut);
t.y=INF;
for(int i=prenum-1;i>=0;i--){
if(ans<pre[i].x){//剪枝,由于圆的半径排过序,圆的半径不大于现有答案时,转break
st=1;
t.x=pre[i].y;
en=upper_bound(lp,lp+cut,t)-lp;
v=pre[i].x+pre[i].y-1;
k=pre[i].y;
if(st<=en)
ans=max(ans,max(query(1,1,cut)-t.x,0));
}else
break;
}
}
return ans;
}
int main(){
scanf("%d",&T);
for(int ppp=1;ppp<=T;ppp++){
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&buf[i]);
printf("Case #%d: %d\n",ppp,manachar()/2*3);
}
}
测试数据:
input:
4
10
2 3 4 4 3 2 2 3 4 4
17
1 1 1 1 5 4 4 5 1 1 1 1 5 4 4 5 1
5
1 2 3 4 5
15
2 3 4 4 3 2 2 3 4 4 3 2 2 3 4
output:
9
12
0
9
Hotaru Ichijou recently is addicated to math problems. Now she is playing with N-sequence.
Let's define N-sequence, which is composed with three parts and satisfied with the following condition:
1. the first part is the same as the thrid part,
2. the first part and the second part are symmetrical.
for example, the sequence 2,3,4,4,3,2,2,3,4 is a N-sequence, which the first part 2,3,4 is the same as the thrid part 2,3,4, the first part 2,3,4 and the second part 4,3,2 are symmetrical.
Give you n positive intergers, your task is to find the largest continuous sub-sequence, which is N-sequence.
Let's define N-sequence, which is composed with three parts and satisfied with the following condition:
1. the first part is the same as the thrid part,
2. the first part and the second part are symmetrical.
for example, the sequence 2,3,4,4,3,2,2,3,4 is a N-sequence, which the first part 2,3,4 is the same as the thrid part 2,3,4, the first part 2,3,4 and the second part 4,3,2 are symmetrical.
Give you n positive intergers, your task is to find the largest continuous sub-sequence, which is N-sequence.
For each test case:
the first line of input contains a positive integer N(1<=N<=100000), the length of a given sequence
the second line includes N non-negative integers ,each interger is no larger than
![](https://i-blog.csdnimg.cn/blog_migrate/a22e580c04f29f0f25e4262eec591fd5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1b08ce66336b4f2b3a7b911c59c311d2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/094f0c54ab74a17baaa3bd2c27e2cbb6.png)
We guarantee that the sum of all answers is less than 800000.
1 10 2 3 4 4 3 2 2 3 4 4
Case #1: 9