#include <bits/stdc++.h>
using namespace std;
struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) {}
  bool unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
};
struct edge {
  int to, cost;
};
int main(void) {
  static uint32_t xorarr[200001];
  static int index[67108870];
  static vector<edge> G[200001];
  static int d[200001];
  fill(index, index + 67108870, -1);
  fill(d, d + 200001, 300000);
  string str;
  cin >> str;
  xorarr[0] = 0;
  index[0] = 0;
  for (int i = (0); i < (str.length()); ++i) {
    xorarr[i + 1] = xorarr[i] ^ uint32_t(1 << (str[i] - 'a'));
    if (index[xorarr[i + 1]] == -1)
      index[xorarr[i + 1]] = i + 1;
    else
      G[i + 1].push_back({index[xorarr[i + 1]], 0});
    for (int j = (0); j < (26); ++j) {
      uint32_t temp = xorarr[i + 1] ^ uint32_t(1 << j);
      if (index[temp] != -1) {
        G[i + 1].push_back({index[temp], 1});
      }
    }
  }
  priority_queue<pair<int, int>, vector<pair<int, int>>,
                 greater<pair<int, int>>>
      que;
  d[str.length()] = 0;
  que.push(pair<int, int>(0, str.length()));
  while (!que.empty()) {
    pair<int, int> p = que.top();
    que.pop();
    int v = p.second;
    if (d[v] < p.first) continue;
    for (int i = (0); i < (G[v].size()); ++i) {
      edge e = G[v][i];
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        que.push(pair<int, int>(d[e.to], e.to));
      }
    }
  }
  cout << max(d[0], 1) << endl;
  return 0;
}
