链接
https://vjudge.net/problem/UVA-1470
题解
w
w
r
w
w
r
ww^rww^r
wwrwwr这东西看起来十分回文 我想了半天,发现可以这样判断一个子串是否符合条件: 假设
w
w
w的长度为
u
u
u 那么第一个
w
w
w和第一个
w
r
w^r
wr之间的位置肯定是一个对称轴,两边长度为
u
u
u的区域是关于这个轴对称的,也就是说这里有一个长度不低于
u
u
u的回文串 再以第一个
w
r
w^r
wr和第二个
w
w
w的中心为轴,肯定有一个长度不低于
2
u
2u
2u的回文串 令
a
i
a_i
ai表示以
i
i
i和
i
+
1
i+1
i+1的缝隙为对称轴的回文串的长度 那么一个
w
w
r
w
w
r
ww^rww^r
wwrwwr就体现在
a
a
a序列中有两个数
a
j
,
a
j
(
i
<
j
)
a_j,a_j(i<j)
aj,aj(i<j),满足
a
i
≥
u
a_i\geq u
ai≥u,
a
j
≥
2
u
a_j \geq 2u
aj≥2u,且
j
−
i
=
u
j-i=u
j−i=u 那么现在就是序列问题了 我如果枚举
i
i
i,那么就成了找满足
a
i
≥
j
−
i
a_i \geq j-i
ai≥j−i,
a
j
≥
2
j
−
2
i
a_j \geq 2j-2i
aj≥2j−2i的最大的
j
j
j 化简一下得,
i
≤
j
≤
i
+
a
i
i\leq j \leq i+a_i
i≤j≤i+ai,
2
j
−
a
j
≤
2
i
2j-a_j \leq 2i
2j−aj≤2i 其实就是在
[
i
,
i
+
a
i
]
[i,i+a_i]
[i,i+ai]这个区间去找满足条件
2
j
−
a
j
≤
2
i
2j-a_j\leq 2i
2j−aj≤2i的最大的
j
j
j 因为
2
i
2i
2i单调增加,所以我可以把所有的
j
j
j按照
2
j
−
a
j
2j-a_j
2j−aj排序,用一个指针每次往后移动一下把符合条件的
j
j
j加到树状数组中去,每次查询
[
1
,
i
+
a
i
]
[1,i+a_i]
[1,i+ai]的前缀最小值,如果最小值
x
x
x不小于
i
i
i,那么就用
u
=
x
−
i
u=x-i
u=x−i更新答案
代码
#include <bits/stdc++.h>
#define maxn 600010
#define lowbit(x) ((x)&-(x))
#define cl(x) memset(x,0,sizeof(x))
using namespace std
;
struct Manacher
{
int r
[maxn
], p
[maxn
], n
;
void clear(){cl(r
), cl(p
);}
void calc(int *s
, int N
)
{
n
=N
;
int i
, j
, mx(0), center
;
r
[0]=-2;
for(i
=1;i
<=N
;i
++)r
[2*i
]=s
[i
];
for(i
=1;i
<=N
;i
++)r
[2*i
-1]=-1;
r
[2*N
+1]=-1;
for(i
=1;i
<=2*N
+1;i
++)
{
if(mx
>=i
)p
[i
]=min(p
[2*center
-i
],mx
-i
+1);
else p
[i
]=1;
while(r
[i
-p
[i
]]==r
[i
+p
[i
]])p
[i
]++;
if(i
+p
[i
]-1>mx
)
{
mx
=i
+p
[i
]-1;
center
=i
;
}
}
}
}mnc
;
struct BIT
{
int a
[maxn
], n
;
void clear(){cl(a
);}
void add(int pos
, int v
)
{
for(;pos
<=n
;pos
+=lowbit(pos
))a
[pos
]=max(a
[pos
],v
);
}
int pre_max(int pos
)
{
int ans(0);
for(;pos
;pos
-=lowbit(pos
))ans
=max(ans
,a
[pos
]);
return ans
;
}
}bit
;
char s
[maxn
];
int len
, r
[maxn
], a
[maxn
];
void init()
{
int i
;
scanf("%s",s
+1);
len
=strlen(s
+1);
cl(r
);
for(i
=1;i
<=len
;i
++)r
[i
]=s
[i
];
mnc
.clear();
mnc
.calc(r
,len
);
}
vector
< pair
<int,int> > d
;
void work()
{
int i
, j
, x
, ans(0), p(0);
for(i
=1;i
<=len
;i
++)
a
[i
]=(mnc
.p
[i
*2+1]-1)/2;
d
.clear();
for(j
=1;j
<=len
;j
++)
d
.emplace_back( make_pair(j
-a
[j
]/2,j
) );
sort(d
.begin(),d
.end());
bit
.clear();
bit
.n
=len
;
for(i
=1;i
<=len
;i
++)
{
while(p
<d
.size())
{
if(d
.at(p
).first
<= i
)
{
bit
.add(d
.at(p
).second
,d
.at(p
).second
);
p
++;
}
else break;
}
j
=bit
.pre_max(i
+a
[i
]);
if(j
>=i
)ans
=max(ans
,j
-i
);
}
printf("%d\n",ans
*4);
}
int main()
{
int T
;
scanf("%d",&T
);
while(T
--)
{
init();
work();
}
return 0;
}