嗯,這道題是迴文樹的裸題。
簡單講一下回文樹。
也可以看看這個迴文樹筆記(轉自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;
}