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;

const INF: u32 = 1 << 30 as u32;

fn main() {
    let sc = std::io::stdin();
    let mut sc = Scanner { reader: sc.lock() };
    let s: Vec<u32> = sc
        .read::<String>()
        .chars()
        .map(|c| c as u32 - 'a' as u32)
        .collect();
    let n = s.len();
    let mut hash: Vec<u32> = vec![0; n + 1];
    for i in 0..n {
        hash[i + 1] = hash[i] ^ (1 << s[i]);
    }

    let mut prefix: Vec<u32> = vec![0];
    for i in 0..26 {
        prefix.push(1 << i);
    }

    let mut opt = vec![INF; n + 1];
    let mut dp = vec![INF; 1 << 26];
    opt[0] = 0;
    dp[0] = 0;

    for i in 0..n {
        let hash = hash[i + 1];
        for &prefix in prefix.iter() {
            let suffix = hash ^ prefix;
            opt[i + 1] = cmp::min(opt[i + 1], dp[suffix as usize] + 1);
        }
        dp[hash as usize] = cmp::min(dp[hash as usize], opt[i + 1]);
    }

    println!("{}", opt[n]);
}

pub struct Scanner<R> {
    reader: R,
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .reader
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n')
            .take_while(|&b| b != b' ' && b != b'\n')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn read_vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}