题目链接:http://codeforces.com/problemset/problem/159/D;
/*
题目大意:求一个字符串内不覆盖的回文串对数;
思路;首先可以用manacher求出一个p 序列,记录的是以当前字母为中心是回文串的长度,然后求一
下包括当前字母前面的字母形成回文串的总数(前缀和),包括后面的字母利用了前面的字母
形成的回文穿。
举个列子:aabaa manacher转换后的字符串应为 # a # a # b # a # a
前缀和就是 0 3 3 5 5 6 6 8 8 9
下标 1 2 3 4 5 6 7 8 9 10
最后枚举每个回文串右端的回文串个数相加就是答案;
具体可以看代码 (^ω^)
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=2e4+10;
char str[N];
ll p[N],sum[N];
int main()
{
scanf("%s",str);
int len=strlen(str),id=0;
for(int i=len; i>=0; i--)
{
str[i*2+2]=str[i];
str[i*2+1]='#';
}
str[0]='*';
for(int i=2; i<=len*2; ++i)
{
if(p[id]+id>i) p[i]=p[2*id-i]>p[id]+id-i?p[id]+id-i:p[2*id-i];
else p[i]=1;
while(str[i-p[i]]==str[i+p[i]]) p[i]++;
if(id+p[id]<i+p[i]) id=i;
}
for(int i=1; i<=len*2; ++i)
{
if(i&1)
for(int j=1; j<p[i]; j+=2)
sum[i-j]++;
else
for(int j=0; j<p[i]; j+=2)
sum[i-j]++;
}
for(int i=1;i<=len*2;++i) sum[i]+=sum[i-1];
for(int i=1;i<=len*2;++i) printf("%lld ",sum[i]); printf("\n");
ll ans=0;
for(int i=1; i<=len*2; ++i)
{
if(i&1)
for(int j=1; j<p[i]; j+=2)
ans+=sum[len*2]-sum[i+j];
else
for(int j=0; j<p[i]; j+=2)
ans+=sum[len*2]-sum[i+j];
}
printf("%lld\n",ans);
return 0;
}