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: Wrong Answer)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int, int>;
const ll MOD = 1000000007;

string s;
int N;
int pos2bit[200005];
map<int, vector<int>> bit2pos;
int memo[200005];
int best;

int dfs(int pos, int cur){
    if(pos == N) return 0;
    if(cur + 1 >= best) return N;
    if(memo[pos] != -1) return memo[pos];
    int bit = pos2bit[pos];
    int ret = 2 * N;
    {
        const vector<int>& cand = bit2pos[bit];
        if(cand.size() != 0){
            auto it = cand.end();
            while(true){
                it--;
                if(*it <= pos) break;
                int res = dfs(*it, cur + 1);
                best = min(best, cur + 1 + res);
                ret = min(ret, 1 + res);
                if(it == cand.begin()) break;
            }
        }
    }
    for(int i=0;i<26;i++){
        int nbit = bit ^ (1 << i);
        const vector<int>& cand = bit2pos[nbit];
        if(cand.size() == 0) continue;
        auto it = cand.end();
        while(true){
            it--;
            if(*it <= pos) break;
            int res = dfs(*it, cur + 1);
            best = min(best, cur + 1 + res);
            ret = min(ret, 1 + res);
            if(it == cand.begin()) break;
        }
    }
    memo[pos] = ret;
    return ret;
}

int main(){
    cin >> s;

    N = s.size();
    best = 2 * N;
    int bit = 0;
    pos2bit[0] = 0;
    for(int i=0;i<s.size();i++){
        int c = int(s[i] - 'a');
        bit ^= (1 << c);
        pos2bit[i + 1] = bit;
        bit2pos[bit].push_back(i + 1);
    }

    memset(memo, -1, sizeof(memo));
    cout << dfs(0, 0) << endl;

    return 0;
}