# I Love Palindrome String

### I Love Palindrome String

#### 题目描述

You are given a string S=s1s2..s|S| containing only lowercase English letters. For each integer i∈[1,|S|] , please output how many substrings slsl+1...srsatisfy the following conditions:
∙ r−l+1 equals to i.
∙ The substring slsl+1...sr is a palindrome string.
∙ slsl+1...s⌊(l+r)/2⌋ is a palindrome string too.
|S| denotes the length of string S.
A palindrome string is a sequence of characters which reads the same backward as forward, such as madam or racecar or abba.

#### 输入

There are multiple test cases.
Each case starts with a line containing a string S(1≤|S|≤3×105) containing only lowercase English letters.
It is guaranteed that the sum of |S| in all test cases is no larger than 4×106.

#### 输出

For each test case, output one line containing |S| integers. Any two adjacent integers are separated by a space.

#### 样例输入

abababa


#### 样例输出

7 0 0 0 3 0 0

题意：求有多少个字符串为回文串，且它的前一半也是回文串。回文树+马拉车。先用回文树求出全部的本质不一样（就是长度不一样，或者长度一样内容不一样）的字符串，然后用马拉车快速判断该串是不是符合题意。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 300005 ;
const int N = 26 ;

int Palindromic_Length[MAXN*2];
int ans[MAXN];

struct Palindromic_Tree
{
int nxt[MAXN][26],f[MAXN],cnt[MAXN],num[MAXN],len[MAXN],c[MAXN],last,n,L;

int l[MAXN],r[MAXN];

inline int newnode(int x)
{
for(register int i=0; i<26; ++i)
nxt[L][i]=0;
cnt[L]=0;
len[L]=x;
return L++;
}
void init()
{
L=0;
newnode(0);
newnode(-1);
last=0;
n=0;
c[n]=-1;
f[0]=1;
}
inline int getf(int x)
{
while(c[n-len[x]-1]!=c[n])
x=f[x];
return x;
}
{
x-='a';
c[++n]=x;
int cur=getf(last);
if(!nxt[cur][x])
{
int now=newnode(len[cur]+2);

l[now]=n-len[cur]-1;
r[now]=n;

f[now]=nxt[getf(f[cur])][x];
nxt[cur][x]=now;
}
++cnt[last=nxt[cur][x]];
}
void count()
{
for(register int i=L-1; i>=2; --i)
cnt[f[i]]+=cnt[i];
}

void getans()
{
count();
for(int i=2;i<L;i++)
{
int l1=l[i],r1=r[i];
r1=(l1+r1)/2;

r1*=2;
l1*=2;

int mid=(r1+l1)/2;

if(mid-Palindromic_Length[mid]+1<=(l1))
{
ans[len[i]]+=cnt[i];
}
}
}

} PT;

string Manacher(string s)
{
/*改造字符串*/
string res="\$#";
for(int i=0; i<s.size(); ++i)
{
res+=s[i];
res+="#";
}

/*数组*/
vector<int> P(res.size(),0);
int mi=0,right=0;   //mi为最大回文串对应的中心点，right为该回文串能达到的最右端的值
int maxLen=0,maxPoint=0;    //maxLen为最大回文串的长度，maxPoint为记录中心点

for(int i=1; i<res.size(); ++i)
{
P[i]=right>i ?min(P[2*mi-i],right-i):1;     //关键句，文中对这句以详细讲解

while(res[i+P[i]]==res[i-P[i]])
++P[i];

if(right<i+P[i])    //超过之前的最右端，则改变中心点和对应的最右端
{
right=i+P[i];
mi=i;
}

if(maxLen<P[i])     //更新最大回文串的长度，并记下此时的点
{
maxLen=P[i];
maxPoint=i;
}
Palindromic_Length[i]=P[i]-1;

// printf("%d %d %c\n",i,P[i]-1,res[i]);

}
return s.substr((maxPoint-maxLen)/2,maxLen-1);
}

Palindromic_Tree tree;
int main()
{
char s[MAXN];

while(scanf("%s",s)==1)
{
string a(s);
tree.init();

int len=strlen(s);
}