题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6599
利用回文树找出所有的回文串(记录出现的位置)
然后利用哈希判断回文串的一半是否也是回文串即可
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 300010;
const ull base = 131;
int n, tot;
int tail, last;
ull has[maxn], rhash[maxn], po[maxn];
int ans[maxn];
struct PAM{
int len, fail, son[30], sz, pos;
}t[maxn];
char s[maxn];
int Get_Fail(int x){
while(s[tail - t[x].len - 1] != s[tail]) x = t[x].fail;
return x;
}
void Extend(int x){
int cur = Get_Fail(last);
if(!t[cur].son[x]){
++tot;
t[tot].len = t[cur].len + 2;
t[tot].fail = t[Get_Fail(t[cur].fail)].son[x];
t[tot].pos = tail;
t[cur].son[x] = tot;
}
++t[t[cur].son[x]].sz;
last = t[cur].son[x];
}
void count(){
for(int i = tot ; i >= 2 ; --i){
t[t[i].fail].sz += t[i].sz;
}
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
po[0] = 1;
for(int i = 1 ; i <= 300000 ; ++i) po[i] = po[i - 1] * base;
while(scanf("%s", s + 1) != EOF){
memset(t, 0, sizeof(t));
memset(ans, 0, sizeof(ans));
memset(rhash, 0, sizeof(rhash));
memset(has, 0, sizeof(has));
n = strlen(s + 1);
for(int i = 1 ; i <= n ; ++i) has[i] = has[i - 1] * base + s[i] - 'a';
rhash[n + 1] = 0;
for(int i = n ; i >= 1 ; --i) rhash[i] = rhash[i + 1] * base + s[i] - 'a';
t[0].len = 0, t[1].len = -1;
t[0].fail = t[1].fail = 1;
last = 1; tot = 1;
for(tail = 1 ; tail <= n ; ++tail){
Extend(s[tail] - 'a');
}
count();
for(int i = 2 ; i <= tot ; ++i){
int len2 = (t[i].len & 1) ? t[i].len / 2 + 1 : t[i].len / 2;
int len = len2 / 2;
int mid = t[i].pos - ((t[i].len & 1) ? ((t[i].len / 2) + 1) : t[i].len / 2) + 1;
// printf("%d %d %d\n", t[i].pos, t[i].len, mid);
int HR = has[t[i].pos] - has[t[i].pos - len] * po[len];
int HL = rhash[mid] - rhash[mid + len] * po[len];
if(HL == HR){
ans[t[i].len] += t[i].sz;
}
}
for(int i = 1 ; i <= n ; ++i) {
if(i == 1) printf("%d", ans[i]);
else printf(" %d", ans[i]);
}
puts("");
}
return 0;
}