#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
#define ll long long
#define ull unsigned long long
#define ld long double
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vc vector<char>
#define vs vector<string>
#define vpll vector<pll>
#define vpii vector<pii>
#define umap unordered_map
#define uset unordered_set
#define PQ priority_queue
#define printa(a,L,R) for(int i=L;i<R;i++) cout<<a[i]<<(i==R-1?'\n':' ')
#define printv(a) printa(a,0,a.size())
#define print2d(a,r,c) for(int i=0;i<r;i++) for(int j=0;j<c;j++) cout<<a[i][j]<<(j==c-1?'\n':' ')
#define pb push_back
#define eb emplace_back
#define mt make_tuple
#define fbo find_by_order
#define ook order_of_key
#define MP make_pair
#define UB upper_bound
#define LB lower_bound
#define SQ(x) ((x)*(x))
#define issq(x) (((ll)(sqrt((x))))*((ll)(sqrt((x))))==(x))
#define F first
#define S second
#define mem(a,x) memset(a,x,sizeof(a))
#define inf 1e18
#define E 2.71828182845904523536
#define gamma 0.5772156649
#define nl "\n"
#define lg(r,n) (int)(log2(n)/log2(r))
#define pf printf
#define sf scanf
#define sf1(a) scanf("%d",&a)
#define sf2(a,b) scanf("%d %d",&a,&b)
#define sf3(a,b,c) scanf("%d %d %d",&a,&b,&c)
#define pf1(a) printf("%d\n",a);
#define pf2(a,b) printf("%d %d\n",a,b)
#define pf3(a,b,c) printf("%d %d %d\n",a,b,c)
#define sf1ll(a) scanf("%lld",&a)
#define sf2ll(a,b) scanf("%I64d %I64d",&a,&b)
#define sf3ll(a,b,c) scanf("%I64d %I64d %I64d",&a,&b,&c)
#define pf1ll(a) printf("%lld\n",a);
#define pf2ll(a,b) printf("%I64d %I64d\n",a,b)
#define pf3ll(a,b,c) printf("%I64d %I64d %I64d\n",a,b,c)
#define _ccase printf("Case %lld: ",++cs)
#define _case cout<<"Case "<<++cs<<": "
#define by(x) [](const auto& a, const auto& b) { return a.x < b.x; }
#define asche cerr<<"Ekhane asche\n";
#define rev(v) reverse(v.begin(),v.end())
#define srt(v) sort(v.begin(),v.end())
#define grtsrt(v) sort(v.begin(),v.end(),greater<ll>())
#define all(v) v.begin(),v.end()
#define mnv(v) *min_element(v.begin(),v.end())
#define mxv(v) *max_element(v.begin(),v.end())
#define toint(a) atoi(a.c_str())
#define BeatMeScanf ios_base::sync_with_stdio(false)
#define valid(tx,ty) (tx>=0&&tx<n&&ty>=0&&ty<m)
#define one(x) __builtin_popcount(x)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define stree l=(n<<1),r=l+1,mid=b+(e-b)/2
#define fout(x) fixed<<setprecision(x)
string tostr(int n) {stringstream rr;rr<<n;return rr.str();}
inline void yes(){cout<<"YES\n";exit(0);}
inline void no(){cout<<"NO\n";exit(0);}
template <typename T> using o_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
//ll dx[]={1,0,-1,0,1,-1,-1,1};
//ll dy[]={0,1,0,-1,1,1,-1,-1};
//random_device rd;
//mt19937 random(rd());
#define debug(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); deb(_it, args); }
void deb(istream_iterator<string> it) {}
template<typename T, typename... Args>
void deb(istream_iterator<string> it, T a, Args... args) {
cerr << *it << " = " << a << endl;
deb(++it, args...);
}
const int mod=1e9+7;
const int N=3e5+9;
const ld eps=1e-9;
const ld PI=acos(-1.0);
//ll gcd(ll a,ll b){while(b){ll x=a%b;a=b;b=x;}return a;}
//ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
//ll qpow(ll n,ll k) {ll ans=1;assert(k>=0);n%=mod;while(k>0){if(k&1) ans=(ans*n)%mod;n=(n*n)%mod;k>>=1;}return ans%mod;}
///There can be at most n unique palindromes for a string of size n
struct node ///a node is a palindromic substring of the string
{
int nxt[26]; ///link to the palindrome which is formed by adding
///next[i] in both side of this palindrome
int len; ///length of the palindrome
int st,en; ///starting and ending index of the node
int suflink; ///link to the maximum proper suffix palindrome of the node
int cnt; ///stores the length of the suffix link chain from it (including this node)
///i.e. the number of palindromic suffix of this node
int oc; ///stores the number of occurrence of the node
int diff; ///difference diff[v] = len[v]−len[suflink[v]]
int serieslink; ///longest suffix-palindrome of v having the difference unequal to diff[v].
};
string s;
node t[N];
int n; ///size of string
int sz; ///indicates size of the tree
int suf; ///index of maximum suffix palindrome
void init()
{
t[1].diff=t[2].diff=0;
sz=2,suf=2;
t[1].len=-1,t[1].suflink=t[1].serieslink=1; ///node 1- root with length -1
t[2].len=0,t[2].suflink=1;t[2].serieslink=2; ///node 2- root with length 0 i.e null palindrome
}
/// return if creates a new palindrome
int add_letter(int pos)
{
///find the maximum suffix of the prefix+s[pos]
int cur=suf,curlen=0;
int ch=s[pos]-'a';
while(1){
curlen=t[cur].len;
if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos]) break;
cur=t[cur].suflink;
}
///if the node is not created yet then create the new node
if(t[cur].nxt[ch]){
suf=t[cur].nxt[ch];
t[suf].oc++;
return 0;
}
sz++;
suf=sz;
t[sz].oc=1;
t[sz].len=t[cur].len+2;
t[cur].nxt[ch]=sz;
t[sz].en=pos;
t[sz].st=pos-t[sz].len+1;
if(t[sz].len==1){
t[sz].diff=1;
t[sz].serieslink=2;
t[sz].suflink=2;
t[sz].cnt=1;
return 1;
}
while(1){
cur=t[cur].suflink;
curlen=t[cur].len;
if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos]){
t[sz].suflink=t[cur].nxt[ch];
break;
}
}
t[sz].cnt=1+t[t[sz].suflink].cnt;
t[sz].diff=t[sz].len-t[t[sz].suflink].len;
if(t[sz].diff==t[t[sz].suflink].diff) t[sz].serieslink=t[t[sz].suflink].serieslink;
else t[sz].serieslink=t[sz].suflink;
return 1;
}
int ans[N][2],dp[N][2],kfact[N];
int getmin(int pos,int v,int k)
{
dp[v][k]=ans[pos-t[v].len][k];
if (t[v].diff == t[t[v].suflink].diff){
dp[v][k] = min(dp[v][k], dp[t[v].suflink][k]);
dp[v][k] =min(dp[v][k], ans[pos - t[t[v].serieslink].len- t[v].diff][k]);
}
return dp[v][k] + 1;
}
void calc(int pos,int cur)
{
pos++;
ans[pos][0]=1e9;
ans[pos][1]=1e9;
for(int v=cur;t[v].len>0;v=t[v].serieslink){
ans[pos][0]=min(ans[pos][0],getmin(pos,v,1));
ans[pos][1]=min(ans[pos][1],getmin(pos,v,0));
}
}
///ans[i][0]=minimal even k (or −2 if it doesn’t exist) such that
///we can split string s[1.. i] into k palindromes.
///ans[i][1]=minimal odd k (or −1 if it doesn’t exist) such that
///we can split string s[1.. i] into k palindromes.
///k-palindrome factorization=splitting the string into k non-empty non-intersecting palindromes
///minimum palindrome factorization=minimum k such that k-palindrome factorization exist
int main()
{
BeatMeScanf;
int i,j,k,n,m;
cin>>s;
n=s.size();
init();
ans[0][1]=1e9;
dp[2][1]=1e9;
for(i=0;i<n;i++){
add_letter(i);
calc(i,suf);
}
for(i=1;i<=n;i++) cout<<(ans[i][1]==1e9?-1:ans[i][1])<<' '<<(ans[i][0]==1e9?-2:ans[i][0])<<nl;
///minimum palindrome factorization
int res=min(ans[n][0],ans[n][1]);
cout<<res<<nl;
///if k-palindrome factorization is possible or not
for(i=ans[n][1];i<=n;i+=2) kfact[i]=1;
for(i=ans[n][0];i<=n;i+=2) kfact[i]=1;
for(i=1;i<=n;i++) cout<<(kfact[i]?"YES\n":"NO\n");
return 0;
}
I3ByYWdtYSBjb21tZW50KGxpbmtlciwgIi9zdGFjazoyMDAwMDAwMDAiKQojcHJhZ21hIEdDQyBvcHRpbWl6ZSgiT2Zhc3QiKQojcHJhZ21hIEdDQyB0YXJnZXQoInNzZSxzc2UyLHNzZTMsc3NzZTMsc3NlNCxwb3BjbnQsYWJtLG1teCxhdngsdHVuZT1uYXRpdmUiKQojcHJhZ21hIEdDQyBvcHRpbWl6ZSgidW5yb2xsLWxvb3BzIikKCiNpbmNsdWRlPGJpdHMvc3RkYysrLmg+CiNpbmNsdWRlPGV4dC9wYl9kcy9hc3NvY19jb250YWluZXIuaHBwPgojaW5jbHVkZTxleHQvcGJfZHMvdHJlZV9wb2xpY3kuaHBwPgp1c2luZyBuYW1lc3BhY2UgX19nbnVfcGJkczsKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCiNkZWZpbmUgbGwgbG9uZyBsb25nCiNkZWZpbmUgdWxsIHVuc2lnbmVkIGxvbmcgbG9uZwojZGVmaW5lIGxkIGxvbmcgZG91YmxlCiNkZWZpbmUgcGlpIHBhaXI8aW50LGludD4KI2RlZmluZSBwbGwgcGFpcjxsbCxsbD4KI2RlZmluZSB2aSB2ZWN0b3I8aW50PgojZGVmaW5lIHZsbCB2ZWN0b3I8bGw+CiNkZWZpbmUgdmMgdmVjdG9yPGNoYXI+CiNkZWZpbmUgdnMgdmVjdG9yPHN0cmluZz4KI2RlZmluZSB2cGxsIHZlY3RvcjxwbGw+CiNkZWZpbmUgdnBpaSB2ZWN0b3I8cGlpPgojZGVmaW5lIHVtYXAgdW5vcmRlcmVkX21hcAojZGVmaW5lIHVzZXQgdW5vcmRlcmVkX3NldAojZGVmaW5lIFBRIHByaW9yaXR5X3F1ZXVlCgojZGVmaW5lIHByaW50YShhLEwsUikgZm9yKGludCBpPUw7aTxSO2krKykgY291dDw8YVtpXTw8KGk9PVItMT8nXG4nOicgJykKI2RlZmluZSBwcmludHYoYSkgcHJpbnRhKGEsMCxhLnNpemUoKSkKI2RlZmluZSBwcmludDJkKGEscixjKSBmb3IoaW50IGk9MDtpPHI7aSsrKSBmb3IoaW50IGo9MDtqPGM7aisrKSBjb3V0PDxhW2ldW2pdPDwoaj09Yy0xPydcbic6JyAnKQojZGVmaW5lIHBiIHB1c2hfYmFjawojZGVmaW5lIGViIGVtcGxhY2VfYmFjawojZGVmaW5lIG10IG1ha2VfdHVwbGUKI2RlZmluZSBmYm8gZmluZF9ieV9vcmRlcgojZGVmaW5lIG9vayBvcmRlcl9vZl9rZXkKI2RlZmluZSBNUCBtYWtlX3BhaXIKI2RlZmluZSBVQiB1cHBlcl9ib3VuZAojZGVmaW5lIExCIGxvd2VyX2JvdW5kCiNkZWZpbmUgU1EoeCkgKCh4KSooeCkpCiNkZWZpbmUgaXNzcSh4KSAoKChsbCkoc3FydCgoeCkpKSkqKChsbCkoc3FydCgoeCkpKSk9PSh4KSkKI2RlZmluZSBGIGZpcnN0CiNkZWZpbmUgUyBzZWNvbmQKI2RlZmluZSBtZW0oYSx4KSBtZW1zZXQoYSx4LHNpemVvZihhKSkKI2RlZmluZSBpbmYgMWUxOAojZGVmaW5lIEUgMi43MTgyODE4Mjg0NTkwNDUyMzUzNgojZGVmaW5lIGdhbW1hIDAuNTc3MjE1NjY0OQojZGVmaW5lIG5sICJcbiIKI2RlZmluZSBsZyhyLG4pIChpbnQpKGxvZzIobikvbG9nMihyKSkKI2RlZmluZSBwZiBwcmludGYKI2RlZmluZSBzZiBzY2FuZgojZGVmaW5lIHNmMShhKSAgICAgICAgICAgICAgICBzY2FuZigiJWQiLCZhKQojZGVmaW5lIHNmMihhLGIpICAgICAgICAgICAgICBzY2FuZigiJWQgJWQiLCZhLCZiKQojZGVmaW5lIHNmMyhhLGIsYykgICAgICAgICAgICBzY2FuZigiJWQgJWQgJWQiLCZhLCZiLCZjKQojZGVmaW5lIHBmMShhKSAgICAgICAgICAgICAgICBwcmludGYoIiVkXG4iLGEpOwojZGVmaW5lIHBmMihhLGIpICAgICAgICAgICAgICBwcmludGYoIiVkICVkXG4iLGEsYikKI2RlZmluZSBwZjMoYSxiLGMpICAgICAgICAgICAgcHJpbnRmKCIlZCAlZCAlZFxuIixhLGIsYykKI2RlZmluZSBzZjFsbChhKSAgICAgICAgICAgICAgc2NhbmYoIiVsbGQiLCZhKQojZGVmaW5lIHNmMmxsKGEsYikgICAgICAgICAgICBzY2FuZigiJUk2NGQgJUk2NGQiLCZhLCZiKQojZGVmaW5lIHNmM2xsKGEsYixjKSAgICAgICAgICBzY2FuZigiJUk2NGQgJUk2NGQgJUk2NGQiLCZhLCZiLCZjKQojZGVmaW5lIHBmMWxsKGEpICAgICAgICAgICAgICBwcmludGYoIiVsbGRcbiIsYSk7CiNkZWZpbmUgcGYybGwoYSxiKSAgICAgICAgICAgIHByaW50ZigiJUk2NGQgJUk2NGRcbiIsYSxiKQojZGVmaW5lIHBmM2xsKGEsYixjKSAgICAgICAgICBwcmludGYoIiVJNjRkICVJNjRkICVJNjRkXG4iLGEsYixjKQojZGVmaW5lIF9jY2FzZSBwcmludGYoIkNhc2UgJWxsZDogIiwrK2NzKQojZGVmaW5lIF9jYXNlIGNvdXQ8PCJDYXNlICI8PCsrY3M8PCI6ICIKI2RlZmluZSBieSh4KSBbXShjb25zdCBhdXRvJiBhLCBjb25zdCBhdXRvJiBiKSB7IHJldHVybiBhLnggPCBiLng7IH0KCiNkZWZpbmUgYXNjaGUgY2Vycjw8IkVraGFuZSBhc2NoZVxuIjsKI2RlZmluZSByZXYodikgcmV2ZXJzZSh2LmJlZ2luKCksdi5lbmQoKSkKI2RlZmluZSBzcnQodikgc29ydCh2LmJlZ2luKCksdi5lbmQoKSkKI2RlZmluZSBncnRzcnQodikgc29ydCh2LmJlZ2luKCksdi5lbmQoKSxncmVhdGVyPGxsPigpKQojZGVmaW5lIGFsbCh2KSB2LmJlZ2luKCksdi5lbmQoKQojZGVmaW5lIG1udih2KSAqbWluX2VsZW1lbnQodi5iZWdpbigpLHYuZW5kKCkpCiNkZWZpbmUgbXh2KHYpICptYXhfZWxlbWVudCh2LmJlZ2luKCksdi5lbmQoKSkKI2RlZmluZSB0b2ludChhKSBhdG9pKGEuY19zdHIoKSkKI2RlZmluZSBCZWF0TWVTY2FuZiBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKQojZGVmaW5lIHZhbGlkKHR4LHR5KSAodHg+PTAmJnR4PG4mJnR5Pj0wJiZ0eTxtKQojZGVmaW5lIG9uZSh4KSBfX2J1aWx0aW5fcG9wY291bnQoeCkKI2RlZmluZSBVbmlxdWUodikgdi5lcmFzZSh1bmlxdWUoYWxsKHYpKSx2LmVuZCgpKQojZGVmaW5lIHN0cmVlIGw9KG48PDEpLHI9bCsxLG1pZD1iKyhlLWIpLzIKI2RlZmluZSBmb3V0KHgpIGZpeGVkPDxzZXRwcmVjaXNpb24oeCkKc3RyaW5nIHRvc3RyKGludCBuKSB7c3RyaW5nc3RyZWFtIHJyO3JyPDxuO3JldHVybiByci5zdHIoKTt9CmlubGluZSB2b2lkIHllcygpe2NvdXQ8PCJZRVNcbiI7ZXhpdCgwKTt9CmlubGluZSB2b2lkIG5vKCl7Y291dDw8Ik5PXG4iO2V4aXQoMCk7fQp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4gdXNpbmcgb19zZXQgPSB0cmVlPFQsIG51bGxfdHlwZSwgbGVzczxUPiwgcmJfdHJlZV90YWcsIHRyZWVfb3JkZXJfc3RhdGlzdGljc19ub2RlX3VwZGF0ZT47Ci8vbGwgZHhbXT17MSwwLC0xLDAsMSwtMSwtMSwxfTsKLy9sbCBkeVtdPXswLDEsMCwtMSwxLDEsLTEsLTF9OwovL3JhbmRvbV9kZXZpY2UgcmQ7Ci8vbXQxOTkzNyByYW5kb20ocmQoKSk7CiNkZWZpbmUgZGVidWcoYXJncy4uLikgeyBzdHJpbmcgX3MgPSAjYXJnczsgcmVwbGFjZShfcy5iZWdpbigpLCBfcy5lbmQoKSwgJywnLCAnICcpOyBzdHJpbmdzdHJlYW0gX3NzKF9zKTsgaXN0cmVhbV9pdGVyYXRvcjxzdHJpbmc+IF9pdChfc3MpOyBkZWIoX2l0LCBhcmdzKTsgfQp2b2lkIGRlYihpc3RyZWFtX2l0ZXJhdG9yPHN0cmluZz4gaXQpIHt9CnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lLi4uIEFyZ3M+CnZvaWQgZGViKGlzdHJlYW1faXRlcmF0b3I8c3RyaW5nPiBpdCwgVCBhLCBBcmdzLi4uIGFyZ3MpIHsKICAgIGNlcnIgPDwgKml0IDw8ICIgPSAiIDw8IGEgPDwgZW5kbDsKICAgIGRlYigrK2l0LCBhcmdzLi4uKTsKfQoKY29uc3QgaW50IG1vZD0xZTkrNzsKY29uc3QgaW50IE49M2U1Kzk7CmNvbnN0IGxkIGVwcz0xZS05Owpjb25zdCBsZCBQST1hY29zKC0xLjApOwovL2xsIGdjZChsbCBhLGxsIGIpe3doaWxlKGIpe2xsIHg9YSViO2E9YjtiPXg7fXJldHVybiBhO30KLy9sbCBsY20obGwgYSxsbCBiKXtyZXR1cm4gYS9nY2QoYSxiKSpiO30KLy9sbCBxcG93KGxsIG4sbGwgaykge2xsIGFucz0xO2Fzc2VydChrPj0wKTtuJT1tb2Q7d2hpbGUoaz4wKXtpZihrJjEpIGFucz0oYW5zKm4pJW1vZDtuPShuKm4pJW1vZDtrPj49MTt9cmV0dXJuIGFucyVtb2Q7fQoKCi8vL1RoZXJlIGNhbiBiZSBhdCBtb3N0IG4gdW5pcXVlIHBhbGluZHJvbWVzIGZvciBhIHN0cmluZyBvZiBzaXplIG4Kc3RydWN0IG5vZGUgICAgICAgICAgICAgLy8vYSBub2RlIGlzIGEgcGFsaW5kcm9taWMgc3Vic3RyaW5nIG9mIHRoZSBzdHJpbmcKewogICAgaW50IG54dFsyNl07ICAgICAgICAvLy9saW5rIHRvIHRoZSBwYWxpbmRyb21lIHdoaWNoIGlzIGZvcm1lZCBieSBhZGRpbmcKICAgICAgICAgICAgICAgICAgICAgICAgLy8vbmV4dFtpXSBpbiBib3RoIHNpZGUgb2YgdGhpcyBwYWxpbmRyb21lCiAgICBpbnQgbGVuOyAgICAgICAgICAgIC8vL2xlbmd0aCBvZiB0aGUgcGFsaW5kcm9tZQogICAgaW50IHN0LGVuOyAgICAgICAgICAvLy9zdGFydGluZyBhbmQgZW5kaW5nIGluZGV4IG9mIHRoZSBub2RlCiAgICBpbnQgc3VmbGluazsgICAgICAgIC8vL2xpbmsgdG8gdGhlIG1heGltdW0gcHJvcGVyIHN1ZmZpeCBwYWxpbmRyb21lIG9mIHRoZSBub2RlCiAgICBpbnQgY250OyAgICAgICAgICAgIC8vL3N0b3JlcyB0aGUgbGVuZ3RoIG9mIHRoZSBzdWZmaXggbGluayBjaGFpbiBmcm9tIGl0IChpbmNsdWRpbmcgdGhpcyBub2RlKQogICAgICAgICAgICAgICAgICAgICAgICAvLy9pLmUuIHRoZSBudW1iZXIgb2YgcGFsaW5kcm9taWMgc3VmZml4IG9mIHRoaXMgbm9kZQogICAgaW50IG9jOyAgICAgICAgICAgICAvLy9zdG9yZXMgdGhlIG51bWJlciBvZiBvY2N1cnJlbmNlIG9mIHRoZSBub2RlCiAgICBpbnQgZGlmZjsgICAgICAgICAgIC8vL2RpZmZlcmVuY2UgZGlmZlt2XSA9IGxlblt2XeKIkmxlbltzdWZsaW5rW3ZdXQogICAgaW50IHNlcmllc2xpbms7ICAgICAvLy9sb25nZXN0IHN1ZmZpeC1wYWxpbmRyb21lIG9mIHYgaGF2aW5nIHRoZSBkaWZmZXJlbmNlIHVuZXF1YWwgdG8gZGlmZlt2XS4KfTsKc3RyaW5nIHM7Cm5vZGUgdFtOXTsKaW50IG47ICAgICAgICAgICAgICAgICAgLy8vc2l6ZSBvZiBzdHJpbmcKaW50IHN6OyAgICAgICAgICAgICAgICAgLy8vaW5kaWNhdGVzIHNpemUgb2YgdGhlIHRyZWUKaW50IHN1ZjsgICAgICAgICAgICAgICAgLy8vaW5kZXggb2YgbWF4aW11bSBzdWZmaXggcGFsaW5kcm9tZQp2b2lkIGluaXQoKQp7CiAgICB0WzFdLmRpZmY9dFsyXS5kaWZmPTA7CiAgICBzej0yLHN1Zj0yOwogICAgdFsxXS5sZW49LTEsdFsxXS5zdWZsaW5rPXRbMV0uc2VyaWVzbGluaz0xOyAgLy8vbm9kZSAxLSByb290IHdpdGggbGVuZ3RoIC0xCiAgICB0WzJdLmxlbj0wLHRbMl0uc3VmbGluaz0xO3RbMl0uc2VyaWVzbGluaz0yOyAgLy8vbm9kZSAyLSByb290IHdpdGggbGVuZ3RoIDAgaS5lIG51bGwgcGFsaW5kcm9tZQp9Ci8vLyByZXR1cm4gaWYgY3JlYXRlcyBhIG5ldyBwYWxpbmRyb21lCmludCBhZGRfbGV0dGVyKGludCBwb3MpCnsKICAgIC8vL2ZpbmQgdGhlIG1heGltdW0gc3VmZml4IG9mIHRoZSBwcmVmaXgrc1twb3NdCiAgICBpbnQgY3VyPXN1ZixjdXJsZW49MDsKICAgIGludCBjaD1zW3Bvc10tJ2EnOwogICAgd2hpbGUoMSl7CiAgICAgICAgY3VybGVuPXRbY3VyXS5sZW47CiAgICAgICAgaWYocG9zLTEtY3VybGVuPj0wJiZzW3Bvcy0xLWN1cmxlbl09PXNbcG9zXSkgYnJlYWs7CiAgICAgICAgY3VyPXRbY3VyXS5zdWZsaW5rOwogICAgfQogICAgLy8vaWYgdGhlIG5vZGUgaXMgbm90IGNyZWF0ZWQgeWV0IHRoZW4gY3JlYXRlIHRoZSBuZXcgbm9kZQogICAgaWYodFtjdXJdLm54dFtjaF0pewogICAgICAgIHN1Zj10W2N1cl0ubnh0W2NoXTsKICAgICAgICB0W3N1Zl0ub2MrKzsKICAgICAgICByZXR1cm4gMDsKICAgIH0KICAgIHN6Kys7CiAgICBzdWY9c3o7CiAgICB0W3N6XS5vYz0xOwogICAgdFtzel0ubGVuPXRbY3VyXS5sZW4rMjsKICAgIHRbY3VyXS5ueHRbY2hdPXN6OwogICAgdFtzel0uZW49cG9zOwogICAgdFtzel0uc3Q9cG9zLXRbc3pdLmxlbisxOwogICAgaWYodFtzel0ubGVuPT0xKXsKICAgICAgICB0W3N6XS5kaWZmPTE7CiAgICAgICAgdFtzel0uc2VyaWVzbGluaz0yOwogICAgICAgIHRbc3pdLnN1Zmxpbms9MjsKICAgICAgICB0W3N6XS5jbnQ9MTsKICAgICAgICByZXR1cm4gMTsKICAgIH0KICAgIHdoaWxlKDEpewogICAgICAgIGN1cj10W2N1cl0uc3VmbGluazsKICAgICAgICBjdXJsZW49dFtjdXJdLmxlbjsKICAgICAgICBpZihwb3MtMS1jdXJsZW4+PTAmJnNbcG9zLTEtY3VybGVuXT09c1twb3NdKXsKICAgICAgICAgICAgICAgIHRbc3pdLnN1Zmxpbms9dFtjdXJdLm54dFtjaF07CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CiAgICB0W3N6XS5jbnQ9MSt0W3Rbc3pdLnN1ZmxpbmtdLmNudDsKICAgIHRbc3pdLmRpZmY9dFtzel0ubGVuLXRbdFtzel0uc3VmbGlua10ubGVuOwogICAgaWYodFtzel0uZGlmZj09dFt0W3N6XS5zdWZsaW5rXS5kaWZmKSB0W3N6XS5zZXJpZXNsaW5rPXRbdFtzel0uc3VmbGlua10uc2VyaWVzbGluazsKICAgIGVsc2UgdFtzel0uc2VyaWVzbGluaz10W3N6XS5zdWZsaW5rOwogICAgcmV0dXJuIDE7Cn0KCmludCBhbnNbTl1bMl0sZHBbTl1bMl0sa2ZhY3RbTl07CgppbnQgZ2V0bWluKGludCBwb3MsaW50IHYsaW50IGspCnsKICAgIGRwW3ZdW2tdPWFuc1twb3MtdFt2XS5sZW5dW2tdOwogICAgaWYgKHRbdl0uZGlmZiA9PSB0W3Rbdl0uc3VmbGlua10uZGlmZil7CiAgICAgICAgZHBbdl1ba10gPSBtaW4oZHBbdl1ba10sIGRwW3Rbdl0uc3VmbGlua11ba10pOwogICAgICAgIGRwW3ZdW2tdID1taW4oZHBbdl1ba10sIGFuc1twb3MgLSB0W3Rbdl0uc2VyaWVzbGlua10ubGVuLSB0W3ZdLmRpZmZdW2tdKTsKICAgIH0KICAgIHJldHVybiBkcFt2XVtrXSArIDE7Cn0KCnZvaWQgY2FsYyhpbnQgcG9zLGludCBjdXIpCnsKICAgIHBvcysrOwogICAgYW5zW3Bvc11bMF09MWU5OwogICAgYW5zW3Bvc11bMV09MWU5OwogICAgZm9yKGludCB2PWN1cjt0W3ZdLmxlbj4wO3Y9dFt2XS5zZXJpZXNsaW5rKXsKICAgICAgICBhbnNbcG9zXVswXT1taW4oYW5zW3Bvc11bMF0sZ2V0bWluKHBvcyx2LDEpKTsKICAgICAgICBhbnNbcG9zXVsxXT1taW4oYW5zW3Bvc11bMV0sZ2V0bWluKHBvcyx2LDApKTsKICAgIH0KfQoKLy8vYW5zW2ldWzBdPW1pbmltYWwgZXZlbiBrIChvciDiiJIyIGlmIGl0IGRvZXNu4oCZdCBleGlzdCkgc3VjaCB0aGF0Ci8vL3dlIGNhbiBzcGxpdCBzdHJpbmcgc1sxLi4gaV0gaW50byBrIHBhbGluZHJvbWVzLgoKLy8vYW5zW2ldWzFdPW1pbmltYWwgb2RkIGsgKG9yIOKIkjEgaWYgaXQgZG9lc27igJl0IGV4aXN0KSBzdWNoIHRoYXQKLy8vd2UgY2FuIHNwbGl0IHN0cmluZyBzWzEuLiBpXSBpbnRvIGsgcGFsaW5kcm9tZXMuCgovLy9rLXBhbGluZHJvbWUgZmFjdG9yaXphdGlvbj1zcGxpdHRpbmcgIHRoZSBzdHJpbmcgaW50byBrIG5vbi1lbXB0eSBub24taW50ZXJzZWN0aW5nIHBhbGluZHJvbWVzCgovLy9taW5pbXVtIHBhbGluZHJvbWUgZmFjdG9yaXphdGlvbj1taW5pbXVtIGsgc3VjaCB0aGF0IGstcGFsaW5kcm9tZSBmYWN0b3JpemF0aW9uIGV4aXN0CgppbnQgbWFpbigpCnsKICAgIEJlYXRNZVNjYW5mOwogICAgaW50IGksaixrLG4sbTsKICAgIGNpbj4+czsKICAgIG49cy5zaXplKCk7CiAgICBpbml0KCk7CiAgICBhbnNbMF1bMV09MWU5OwogICAgZHBbMl1bMV09MWU5OwogICAgZm9yKGk9MDtpPG47aSsrKXsKICAgICAgICBhZGRfbGV0dGVyKGkpOwogICAgICAgIGNhbGMoaSxzdWYpOwogICAgfQogICAgZm9yKGk9MTtpPD1uO2krKykgY291dDw8KGFuc1tpXVsxXT09MWU5Py0xOmFuc1tpXVsxXSk8PCcgJzw8KGFuc1tpXVswXT09MWU5Py0yOmFuc1tpXVswXSk8PG5sOwoKICAgIC8vL21pbmltdW0gcGFsaW5kcm9tZSBmYWN0b3JpemF0aW9uCiAgICBpbnQgcmVzPW1pbihhbnNbbl1bMF0sYW5zW25dWzFdKTsKICAgIGNvdXQ8PHJlczw8bmw7CgogICAgLy8vaWYgay1wYWxpbmRyb21lIGZhY3Rvcml6YXRpb24gaXMgcG9zc2libGUgb3Igbm90CiAgICBmb3IoaT1hbnNbbl1bMV07aTw9bjtpKz0yKSBrZmFjdFtpXT0xOwogICAgZm9yKGk9YW5zW25dWzBdO2k8PW47aSs9Mikga2ZhY3RbaV09MTsKICAgIGZvcihpPTE7aTw9bjtpKyspIGNvdXQ8PChrZmFjdFtpXT8iWUVTXG4iOiJOT1xuIik7CiAgICByZXR1cm4gMDsKfQo=