时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
abbab
样例输出
-
8
描述
给定一个字符串S,请统计S的所有|S| * (|S| + 1) / 2个子串中(首尾位置不同就算作不同的子串),有多少个是回文字符串?
输入
一个只包含小写字母的字符串S。
对于30%的数据,S长度不超过100。
对于60%的数据,S长度不超过1000。
对于100%的数据,S长度不超过800000。
输出
回文子串的数量
#include<bits/stdc++.h>
using namespace std;
const int MAX=2e6;
char p[MAX],s[MAX];
int len[MAX];
int init(char *str)
{
int n=strlen(str);
for(int i=1,j=0;i<=2*n;j++,i+=2)
{
s[i]='#';
s[i+1]=str[j];
}
s[0]='$';
s[2*n+1]='#';
s[2*n+2]='@';
s[2*n+3]='\n';
return 2*n+1;
}
void manacher(int n)
{
int mx=0,p=0;
for(int i=1;i<=n;i++)
{
if(mx>i)len[i]=min(mx-i,len[2*p-i]);
else len[i]=1;
while(s[i-len[i]]==s[i+len[i]])len[i]++;
if(len[i]+i>mx)mx=len[i]+i,p=i;
}
}
int main()
{
scanf("%s",p);
int n=init(p);
memset(len,0,sizeof len);
manacher(n);
long long ans=0;
for(int i=1;i<=n;i++)ans+=len[i]/2;
cout<<ans<<endl;
return 0;
}