Description
顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为
Input
一行由小写英文字母组成的字符串
Output
一行一个整数,表示最长双回文子串的长度。
Sample Input
baacaabbacabb
Sample Output
12
HINT
样例说明
从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。
对于100%的数据,
2015.4.25新加数据一组
Source
2012国家集训队Round 1 day2
思路
首先maracher跑一遍,然后分别更新一个点
那么计算
还有些细节在代码中讲。
代码
#include <cstdio>
#include <cstring>
const int maxn=100000;
char s[maxn+10],a[(maxn<<1)+10];
int p[(maxn<<1)+10],l[(maxn<<1)+10],r[(maxn<<1)+10],id,rmax,len,ans;
int main()
{
scanf("%s",s+1);
len=strlen(s+1);
a[0]='!';
a[1]='$';
for(register int i=1; i<=len; ++i)
{
a[i<<1]=s[i];
a[i<<1|1]='$';
}
len=len<<1|1;
a[len+1]='*';//预处理
p[1]=id=rmax=1;
for(register int i=2; i<=len; ++i)//maracher
{
if(i>rmax)
{
p[i]=1;
}
else
{
if(rmax-i>p[(id<<1)-i])
{
p[i]=p[(id<<1)-i];
}
else
{
p[i]=rmax-i;
}
}
while(a[i+p[i]]==a[i-p[i]])
{
++p[i];
}
if(i+p[i]-1>rmax)
{
rmax=i+p[i]-1;
id=i;
}
}
int now=0;//now记录最后一个更新的是哪一个位置
for(register int i=1; i<=len; ++i)
{
for(register int j=now+1; j<=i+p[i]; ++j)
{
l[j]=j-i;//从上一个没有更新的位置开始,一直计算到不能用i位置更新为止
}
if(i+p[i]+1>now)
{
now=i+p[i];//更新now值
}
}
//上一次扫描完成后,now一定为n
for(register int i=len; i>=1; --i)
{
for(register int j=now-1; j>=i-p[i]; --j)
{
r[j]=i-j;//这个i-j和上面的j-i可以推出来,因为不考虑预处理时插入的字符'$'
}
if(i-p[i]-1<now)
{
now=i-p[i];
}
}
for(register int i=1; i<=len; i+=2)//只计算预处理时插入的字符
{
if(l[i]+r[i]>ans)
{
ans=l[i]+r[i];
}
}
printf("%d\n",ans);
return 0;
}