After solving seven problems on Timus Online Judge with a word “palindrome” in the problem name, Misha has got an unusual ability. Now, when he reads a word, he can mentally count the number of unique nonempty substrings of this word that are palindromes.
Dima wants to test Misha’s new ability. He adds letters s 1, ..., s n to a word, letter by letter, and after every letter asks Misha, how many different nonempty palindromes current word contains as substrings. Which n numbers will Misha say, if he will never be wrong?
Input
The only line of input contains the string s 1... s n, where s i are small English letters (1 ≤ n ≤ 10 5).
Output
Output n numbers separated by whitespaces, i-th of these numbers must be the number of different nonempty substrings of prefix s 1... s i that are palindromes.
Example
input output aba 1 2 3
题目大意:输出每个前缀本质不同的回文子串的个数。
解题思路:回文自动机刚开始有两个结点,之后每次多出一个结点,就说明有几个不同的回文子串,所以在一边建树一边输出就可以了,不要忘了减去最开始那两个结点。
/*
@Author: Top_Spirit
@Language: C++
*/
#include <bits/stdc++.h>
using namespace std ;
typedef unsigned long long ull ;
typedef long long ll ;
const int Maxn = 1e5 + 10 ;
const int INF = 0x3f3f3f3f ;
const double PI = acos(-1.0) ;
const ull seed = 133 ;
int n ;
struct palindromic_tree{
int Next[Maxn][26] ;
int fail[Maxn] ;
int cnt[Maxn] ;
int num[Maxn] ;
int len[Maxn] ;
int s[Maxn] ;
int last ;
int n, p ;
int newNode (int k){
for (int i = 0; i < 26; i++) Next[p][i] = 0 ;
cnt[p] = 0 ;
num[p] = 0 ;
len[p] = k ;
return p++ ;
}
void init(){
p = 0 ;
newNode(0) ;
newNode(-1) ;
last = 0 ;
n = 0 ;
s[n] = -1 ;
fail[0] = 1 ;
}
int get_fail (int x){
while (s[n - len[x] - 1] != s[n]) x = fail[x] ;
return x ;
}
void add (int c){
c -= 'a' ;
s[++n] = c ;
int cur = get_fail(last) ;
if (!Next[cur][c]){
int Now = newNode(len[cur] + 2) ;
fail[Now] = Next[get_fail(fail[cur])][c] ;
Next[cur][c] = Now ;
num[Now] = num[fail[Now]] + 1 ;
}
last = Next[cur][c] ;
cnt[last]++ ;
}
void Count(){
for (int i = p - 1; i >= 0; i--){
cnt[fail[i]] += cnt[i] ;
}
}
}Tree;
char str[Maxn] ;
int main (){
cin >> str ;
n = strlen(str) ;
Tree.init() ;
for (int i = 0; i < n; i++){
Tree.add(str[i]) ;
cout << Tree.p - 2 ;
if (i < n - 1) cout << " " ;
}
cout << endl ;
return 0 ;
}