LG4287双倍回文(Manacher)
Posted huayucaiji 的博客小屋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LG4287双倍回文(Manacher)相关的知识,希望对你有一定的参考价值。
LG4287双倍回文
解题思路
据说本体有很多乱搞方法,但是可以用 \\(O(n)\\) 得 manacher
解决。
我们按照正常的 manacher
做,我们要验证 \\(i\\) 这个位置是否可以为右半回文串的中心位置。由于右半回文串长度为偶数,所以中心位置只可能为 #
字符。我们找到位置 \\(i\\) 关于 \\(mid\\) 的对称点 \\(j\\)。如果以 \\(i\\) 为中心的最长回文串和以 \\(j\\) 为中心的最长回文串有交集,那么 \\([j,i]\\) 这一段子串去掉 #
就可以形成一个所求的字符串。
我们注意到,还有一些限制条件,例如 \\(mid\\) 是 #
字符。所以我们可以考虑只对为 #
的字符跑 manacher
。
时间复杂度为 \\(O(n)\\)。实测跑得飞快。
代码
//Don\'t act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you\'ll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
using namespace std;
int read()
char ch=getchar();
int f=1,x=0;
while(ch<\'0\'||ch>\'9\')
if(ch==\'-\')
f=-1;
ch=getchar();
while(ch>=\'0\'&&ch<=\'9\')
x=x*10+ch-\'0\';
ch=getchar();
return f*x;
char read_char()
char ch=getchar();
while(!isalpha(ch))
ch=getchar();
return ch;
const int MAXN=1e6+10;
int n,p,mx,m;
int r[MAXN],c[MAXN];
int main()
cin>>n;
c[++m]=27;
for(int i=1;i<=n;i++)
c[++m]=read_char()-\'a\'+1;
c[++m]=27;
int mid=0,mx=0,ans=0;
for(int i=1;i<=m;i+=2)
if(i>mx)
r[i]=1;
else
r[i]=min(r[mid*2-i],mx-i+1);
if(i-r[i]+1<=mid&&i<=mx)
ans=max(ans,(i-mid)*2);
while(i-r[i]>=1&&i+r[i]<=m&&c[i+r[i]]==c[i-r[i]])
r[i]++;
if(i+r[i]-1>mx)
mid=i;
mx=i+r[i]-1;
cout<<ans<<endl;
return 0;
以上是关于LG4287双倍回文(Manacher)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj2342 [Shoi2011]双倍回文 (manacher)
bzoj 2342 [Shoi2011]双倍回文(manacher,set)
题解Casting Spells LA 4975 UVa 1470 双倍回文 SDOI 2011 BZOJ 2342 Manacher