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)

#![allow(unused_imports, unused_variables, dead_code)]
use std::io::*;
use std::fmt::*;
use std::str::*;
use std::cmp::*;
use std::collections::*;

trait InputValue {
    fn parse(s: &str) -> Self;
}

fn read<T: InputValue>() -> T {
    let mut buf = String::new();
    let _ = stdin().read_line(&mut buf);
    T::parse(&buf.trim())
}

fn readnc<T: InputValue>() -> Vec<T> {
    let mut vec = vec![];
    let line: String = read();
    for token in line.split_whitespace() {
        vec.push(T::parse(token));
    }
    vec
}

fn readn<T: InputValue>(n: usize) -> Vec<T> {
    let mut vec = vec![];
    for _ in 0..n {
        vec.push(read());
    }
    vec
}

macro_rules! parse_single_value {
        ($($t:ty),*) => {
            $(
                impl InputValue for $t {
                    fn parse(s: &str) -> $t { s.parse().unwrap() }
                }
            )*
    	}
    }
parse_single_value!(i32, i64, f32, f64, usize, String);

macro_rules! parse_tuple {
    	($($t:ident),*) => {
    		impl<$($t),*> InputValue for ($($t),*) where $($t: InputValue),* {
    			fn parse(s: &str) -> ($($t),*) {
    				let mut tokens = s.split_whitespace();
    				let t = ($($t::parse(tokens.next().unwrap())),*);
    				t
    			}
    		}
    	}
    }
parse_tuple!(A, B);
parse_tuple!(A, B, C);

// ===

const INF: usize = 10000000;

fn main() {
    let s: String = read();
    let s: Vec<u8> = s.into_bytes();

    let mut map = HashMap::new();
    let mut flg = 0;
    let mut pl = 0;
    map.insert(flg, pl);
    pl += 1;

    let n = s.len();
    for i in 0..n {
        let idx = (s[i] - 'a' as u8) as usize;
        flg ^= 1<<idx;
        if !map.contains_key(&flg) {
            map.insert(flg, pl);
            pl += 1;
        }
    }

    let mut dp = vec![INF; n+100];
    let mut last = 0;
    dp[0] = 0;
    flg = 0;
    for i in 0..n {
        let idx = (s[i] - 'a' as u8) as usize;
        flg ^= 1<<idx;

        let mut best = INF;
        for l in 0..26 {
            let bf = flg ^ (1<<l);
            if map.contains_key(&bf) {
                let &bi = map.get(&bf).unwrap();
                best = min(best, dp[bi]);
            }
        }
        let &fi = map.get(&flg).unwrap();
        dp[fi] = min(dp[fi], best + 1);
        last = dp[fi];
    }
    if flg == 0 {
        last = 1;
    }

    println!("{}", last);
}