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 Rust (1.15.1) (judge verdict: Accepted)

use std::cmp::*;
use std::collections::*;

fn main() {
    let s = read::<String>()
        .chars()
        .map(|x| x.to_digit(36).unwrap() - 10)
        .collect::<Vec<_>>();
    let n = s.len();
    let mut a = vec![0usize; n];
    a[0] = 1 << s[0];
    for i in 1..n {
        a[i] = a[i - 1] ^ (1 << s[i]);
    }
    let mut dp = HashMap::new();
    dp.insert(a[0], 1);
    for i in 1..n {
        if a[i].count_ones() <= 1 && !dp.contains_key(&a[i]) {
            dp.insert(a[i], 1);
            continue;
        }
        if !dp.contains_key(&a[i]) {
            dp.insert(a[i], std::i64::MAX);
        }
        for ci in 0..26 {
            let from = a[i] ^ (1 << ci);
            if !dp.contains_key(&from) {
                continue;
            }
            *dp.get_mut(&a[i]).unwrap() = min(dp[&a[i]], dp[&from] + 1);
        }
    }
    println!("{}", dp[&a[n - 1]]);
}

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}