Problem:
Score : 700 points

Problem Statement

We have a string s consisting of lowercase English letters.
Snuke is partitioning s into some number of non-empty substrings.
Let the subtrings obtained be s_1, s_2, ..., s_N from left to right. (Here, s = s_1 + s_2 + ... + s_N holds.)
Snuke wants to satisfy the following condition:

For each i (1 \leq i \leq N), it is possible to permute the characters in s_i and obtain a palindrome.

Find the minimum possible value of N when the partition satisfies the condition.

Constraints

1 \leq |s| \leq 2 \times 10^5

s consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

s

Output

Print the minimum possible value of N when the partition satisfies the condition.

Sample Input 1

aabxyyzz

Sample Output 1

2

The solution is to partition s as aabxyyzz = aab + xyyzz.
Here, aab can be permuted to form a palindrome aba, and xyyzz can be permuted to form a palindrome zyxyz.

Sample Input 2

byebye

Sample Output 2

1

byebye can be permuted to form a palindrome byeeyb.

Sample Input 3

abcdefghijklmnopqrstuvwxyz

Sample Output 3

26

Sample Input 4

abcabcxabcx

Sample Output 4

3

The solution is to partition s as abcabcxabcx = a + b + cabcxabcx.

Solution in C++14 (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <math.h>
#include <cmath>
#include <limits.h>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <functional>
#include <stdio.h>
using namespace std;

long long MOD = 1000000007;

int popcount( int a ) {
    int ret = 0;
    for ( int i = 0; i < 32; i++ ) {
        if ( a & ( 1 << i  ) ) { ret++; } 
    }
    return ret;
}

int main() {
    
    string S;
    cin >> S;
    
    vector<int> hash(S.length());
    
    for ( int i = 0; i < S.length(); i++ ) {
        if ( !i ) { hash[i] = ( 1 << (S[i]-'a' ) ); }
        else { hash[i] = hash[i-1] ^ ( 1 << (S[i]-'a') ); }
    }
    
    vector<int> opt(S.length());
    fill( opt.begin(), opt.end(), INT_MAX );
    opt[0] = 1;
    
    for ( int i = 1; i < S.length(); i++ ) {
        if ( popcount( hash[i] ) <= 1 ) { opt[i] = 1; continue; }
        
        for ( int j = 0; j < i; j++ ) {
            if ( popcount( hash[i] ^ hash[j] ) <= 1 ) {
                opt[i] = min( opt[i], opt[j] + 1 );
            }
            opt[i] = min( opt[i], opt[i-1]+1 );
        }
        // cout << opt[i] << endl;
    }
    
    cout << opt[S.length()-1] << endl;
    
    
    // for ( auto& a : hash ) {
        // string str;
        // for ( int i = 0; i < 26; i++ ) {
            // if ( a & ( 1 << i ) ) { str += "1"; }
            // else { str += "0"; }
        // }
        // cout << str << endl;
    // }
    
    return 0;
}