#include <bits/stdc++.h>
using namespace std;
struct vertex
{
vertex *to[2]={0,0};
vertex *up;
vertex():up(0){}
bool add(char t)
{
if(to[t]) return 0;
vertex *temp=new vertex;
temp->up=this;
to[t]=temp;
return 1;
}
};
template<int delta> struct base
{
private:
vector<int> rad;
string text;
int i;
int n;
vector<vertex*> link;
vertex *root;
public:
base():i(1),n(0)
{
text.push_back('$');
rad.push_back(0);
root=new vertex;
link.push_back(root);
}
bool add_letter(char t)
{
int r=0;
text+=t;
rad.push_back(0);
link.push_back(root);
int s=i;
for(; i<=n+delta; i++)
{
link[i]=link[s-(i-s)];
rad[i]=rad[s-(i-s)];
while(rad[i]-delta>n-i)
rad[i]--,link[i]=link[i]->up;
if(text[i-rad[i]]==text[i+rad[i]+1-delta])
{
r=link[i]->add(t);
link[i]=link[i]->to[t];
rad[i]++;
break;
}
}
n++;
return r;
}
};
struct manacher
{
private:
base<0> even;
base<1> odd;
public:
int add_letter(char t)
{
t-='a';
return odd.add_letter(t)+even.add_letter(t);
}
} me;
main()
{
ios::sync_with_stdio(0);
cin.tie(0);
char t;
while((t=getchar())!='\n')
cout<<me.add_letter(t)<<' ';
cout<<"\n";
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKc3RydWN0IHZlcnRleAp7CiAgICB2ZXJ0ZXggKnRvWzJdPXswLDB9OwogICAgdmVydGV4ICp1cDsKCiAgICB2ZXJ0ZXgoKTp1cCgwKXt9CgogICAgYm9vbCBhZGQoY2hhciB0KQogICAgewogICAgICAgIGlmKHRvW3RdKSByZXR1cm4gMDsKICAgICAgICB2ZXJ0ZXggKnRlbXA9bmV3IHZlcnRleDsKICAgICAgICB0ZW1wLT51cD10aGlzOwogICAgICAgIHRvW3RdPXRlbXA7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9Cn07Cgp0ZW1wbGF0ZTxpbnQgZGVsdGE+IHN0cnVjdCBiYXNlCnsKcHJpdmF0ZToKICAgIHZlY3RvcjxpbnQ+IHJhZDsKICAgIHN0cmluZyB0ZXh0OwogICAgaW50IGk7CiAgICBpbnQgbjsKCiAgICB2ZWN0b3I8dmVydGV4Kj4gbGluazsKICAgIHZlcnRleCAqcm9vdDsKCnB1YmxpYzoKCiAgICBiYXNlKCk6aSgxKSxuKDApCiAgICB7CiAgICAgICAgdGV4dC5wdXNoX2JhY2soJyQnKTsKICAgICAgICByYWQucHVzaF9iYWNrKDApOwogICAgICAgIHJvb3Q9bmV3IHZlcnRleDsKICAgICAgICBsaW5rLnB1c2hfYmFjayhyb290KTsKICAgIH0KCiAgICBib29sIGFkZF9sZXR0ZXIoY2hhciB0KQogICAgewogICAgICAgIGludCByPTA7CiAgICAgICAgdGV4dCs9dDsKICAgICAgICByYWQucHVzaF9iYWNrKDApOwogICAgICAgIGxpbmsucHVzaF9iYWNrKHJvb3QpOwoKICAgICAgICBpbnQgcz1pOwogICAgICAgIGZvcig7IGk8PW4rZGVsdGE7IGkrKykKICAgICAgICB7CiAgICAgICAgICAgIGxpbmtbaV09bGlua1tzLShpLXMpXTsKICAgICAgICAgICAgcmFkW2ldPXJhZFtzLShpLXMpXTsKCiAgICAgICAgICAgIHdoaWxlKHJhZFtpXS1kZWx0YT5uLWkpCiAgICAgICAgICAgICAgICByYWRbaV0tLSxsaW5rW2ldPWxpbmtbaV0tPnVwOwoKICAgICAgICAgICAgaWYodGV4dFtpLXJhZFtpXV09PXRleHRbaStyYWRbaV0rMS1kZWx0YV0pCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHI9bGlua1tpXS0+YWRkKHQpOwogICAgICAgICAgICAgICAgbGlua1tpXT1saW5rW2ldLT50b1t0XTsKICAgICAgICAgICAgICAgIHJhZFtpXSsrOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbisrOwogICAgICAgIHJldHVybiByOwogICAgfQp9OwoKc3RydWN0IG1hbmFjaGVyCnsKcHJpdmF0ZToKICAgIGJhc2U8MD4gZXZlbjsKICAgIGJhc2U8MT4gb2RkOwoKcHVibGljOgogICAgaW50IGFkZF9sZXR0ZXIoY2hhciB0KQogICAgewogICAgCXQtPSdhJzsKICAgICAgICByZXR1cm4gb2RkLmFkZF9sZXR0ZXIodCkrZXZlbi5hZGRfbGV0dGVyKHQpOwogICAgfQp9IG1lOwoKbWFpbigpCiB7CiAgICBpb3M6OnN5bmNfd2l0aF9zdGRpbygwKTsKICAgIGNpbi50aWUoMCk7CiAgICBjaGFyIHQ7CiAgICB3aGlsZSgodD1nZXRjaGFyKCkpIT0nXG4nKQogICAgICAgIGNvdXQ8PG1lLmFkZF9sZXR0ZXIodCk8PCcgJzsKICAgIGNvdXQ8PCJcbiI7Cn0K