#include//CLOCKS_PER_SEC#define se second#define fi first#define ll long long#define Pii pair #define Pli pair #define ull unsigned long long#define ALL(x) x.begin(),x.end()#define pb push_back//#define mp make_pair#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)const int maxn=3e5+10;const int inf=0x3f3f3f3f;const int mod=1e9+7;using namespace std;typedef double db;const db eps=1e-10;const db pi=acos(-1);const int MAXN=300005;const int N=26;int ans[maxn],p[maxn*2];char s[maxn];void Manacher(char *s,int n,int *pa){ pa[0] = 1; for(int i=1,j=0;i<(n<<1)-1;++i){ int p = i >> 1 , q = i - p , r = ((j + 1)>>1) + pa[j] - 1; pa[i] = r < q ? 0 : min(r - q + 1 , pa[(j<<1) - i]); while(0 <= p - pa[i] && q + pa[i] < n && s[p - pa[i]] == s[q + pa[i]]) pa[i]++; if(q + pa[i] - 1 > r) j = i; }}inline bool check(int L,int R) { int mid=L+R>>1; if ((L&1)==(R&1)) return p[mid<<1]>=R-L+2>>1; return p[mid<<1|1]>=R-L+1>>1;}inline bool Check(int L,int R) { int mid=L+R>>1; if (!check(L,mid) || !check(mid+((L&1)!=(R&1)),R)) return false; return true;}struct Palindromic_Tree { int nxt[MAXN][N];//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成 int fail[MAXN];//fail指针,失配后跳转到fail指针指向的节点 int cnt[MAXN]; int st[MAXN];//存放每个回文串的结尾坐标 int len[MAXN];//len[i]表示节点i表示的回文串的长度 int S[MAXN];//存放添加的字符 int last;//指向上一个字符所在的节点,方便下一次add int n;//字符数组指针 int p;//节点指针 int newnode(int l){ //新建节点 for(int i=0;i =0;--i) cnt[fail[i]]+=cnt[i]; //父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串! } void get_ans(){ for(int i=0;i 0){ if(Check(st[i]-len[i],st[i]-1)){ ans[len[i]]+=cnt[i]; } } } }}PAM;int main(){ while(~scanf("%s",&s)){ PAM.init(); int l=strlen(s); for(int i=1;i<=l;i++){ ans[i]=0; } Manacher(s,l,p); for(int i=0;s[i];i++){ PAM.add(s[i]); } PAM.count(); PAM.get_ans(); for(int i=1;i<=l;i++){ printf("%d",ans[i]); if(i!=l) printf(" "); else printf("\n"); } }}