嗯,这道题是回文树的裸题。
简单讲一下回文树。
也可以看看这个回文树笔记(转自quack_quack)
struct PAM {int a[MAXN][MAXC], l[MAXN], fa[MAXN], sz, last;/*a就是next数组,一个节点的next[C]节点非空,表示着存在一个回文串在当前节点表示的回文串两边加上各一个字符C。l表示长度len,在初始化的时候我们要建立两个节点,一个的长度为0,一个的长度为-1。分别表示长度为偶数的回文串和长度为奇数的回文串的fail串fa表示fail,即失配之后走的边,与sam、acautomation的fail差不多*/void init() {l[1] = -1;fa[0] = fa[1] = 1;sz = 1; last = 0;}void Insert(int c, int n) {int p = last;while(s[n-l[p]-1] != s[n]) p = fa[p];if(a[p][c]) { last = a[p][c]; return; }int q = fa[p], np = ++ sz;l[np] = l[p] + 2;while(s[n-l[q]-1] != s[n]) q = fa[q];fa[np] = a[q][c]; a[p][c] = np;last = np;}
} pam;
下边是这道题的代码:(有几个节点,就有几个回文串)
#include<cstdio>
#define MAXN 200005
#define MAXC 26
char s[MAXN];
struct PAM {int a[MAXN][MAXC], l[MAXN], fa[MAXN], sz, last;void init() {l[1] = -1;fa[0] = fa[1] = 1;sz = 1; last = 0;}void Insert(int c, int n) {int p = last;while(s[n-l[p]-1] != s[n]) p = fa[p];if(a[p][c]) { last = a[p][c]; return; }int q = fa[p], np = ++ sz;l[np] = l[p] + 2;while(s[n-l[q]-1] != s[n]) q = fa[q];fa[np] = a[q][c]; a[p][c] = np;last = np;}
} pam;
int main() {scanf("%s", s + 1);pam.init();for(int i = 1; s[i]; ++ i) {pam.Insert(s[i]-'a', i);printf("%d ", pam.sz-1);}return 0;
}