#include <bits/stdc++.h>
using namespace std;
bool isVowel(char c) {
  c = toupper(c);
  return (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U');
}
struct SegmentTreeNode {
  long long val;
  void assignLeaf(long long value) { val = value; }
  void merge(SegmentTreeNode& left, SegmentTreeNode& right) {
    val = max(left.val, right.val);
  }
  long long getValue() { return val; }
};
template <class T, class V>
class SegmentTree {
  SegmentTreeNode* nodes;
  long long N;

 public:
  SegmentTree(T arr[], long long N) {
    this->N = N;
    nodes = new SegmentTreeNode[getSize(N)];
    buildTree(arr, 1, 0, N - 1);
  }
  ~SegmentTree() { delete[] nodes; }
  V getValue(long long lo, long long hi) {
    SegmentTreeNode result = getValue(1, 0, N - 1, lo, hi);
    return result.getValue();
  }
  void update(long long index, T val) { update(1, 0, N - 1, index, val); }

 private:
  void buildTree(T arr[], long long stIndex, long long lo, long long hi) {
    if (lo == hi) {
      nodes[stIndex].assignLeaf(arr[lo]);
      return;
    }
    long long mid = (lo + hi) / 2;
    buildTree(arr, 2 * stIndex, lo, mid);
    buildTree(arr, 2 * stIndex + 1, mid + 1, hi);
    nodes[stIndex].merge(nodes[2 * stIndex], nodes[2 * stIndex + 1]);
  }
  SegmentTreeNode getValue(long long stIndex, long long left, long long right,
                           long long lo, long long hi) {
    if (left == lo && right == hi) return nodes[stIndex];
    long long mid = (left + right) / 2;
    if (lo > mid) return getValue(2 * stIndex + 1, mid + 1, right, lo, hi);
    if (hi <= mid) return getValue(2 * stIndex, left, mid, lo, hi);
    SegmentTreeNode leftResult = getValue(2 * stIndex, left, mid, lo, mid);
    SegmentTreeNode rightResult =
        getValue(2 * stIndex + 1, mid + 1, right, mid + 1, hi);
    SegmentTreeNode result;
    result.merge(leftResult, rightResult);
    return result;
  }
  void update(long long stIndex, long long lo, long long hi, long long index,
              T value) {
    if (lo == hi) {
      nodes[stIndex].assignLeaf(value);
      return;
    }
    long long mid = (lo + hi) / 2;
    if (index <= mid)
      update(2 * stIndex, lo, mid, index, value);
    else
      update(2 * stIndex + 1, mid + 1, hi, index, value);
    nodes[stIndex].merge(nodes[2 * stIndex], nodes[2 * stIndex + 1]);
  }
  long long getSize(long long n) {
    long long size = 1;
    for (; size < N; size <<= 1)
      ;
    return size << 1;
  }
};
long long solve(string& s, long long n, long long k) {
  long long ans = 0;
  long long i;
  long long v = 0;
  long long c = 0;
  for (i = 0; i < (long long)(k); i++) {
    if (isVowel(s[i]))
      ++v;
    else
      ++c;
  }
  if (v <= 2 * c) ++ans;
  for (i = k; i < (long long)(n); i++) {
    if (isVowel(s[i]))
      ++v;
    else
      ++c;
    if (isVowel(s[i - k]))
      --v;
    else
      --c;
    if (v <= 2 * c) ++ans;
  }
  return ans;
}
const long long N = 6e5;
int32_t main(void) {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  long long i, j;
  string s;
  cin >> s;
  long long n = s.length();
  long long pre[n + 1];
  pre[0] = 0;
  for (i = 1; i < (long long)(n + 1); i++)
    pre[i] = isVowel(s[i - 1]) ? pre[i - 1] - 1 : pre[i - 1] + 2;
  long long x = *min_element(pre, pre + n + 1);
  if (x < 0) {
    for (i = 0; i < (long long)(n + 1); i++) pre[i] -= (x);
  }
  long long last[N];
  memset(last, -1, sizeof(last));
  for (i = 0; i < (long long)(n + 1); i++) last[pre[i]] = i;
  long long ans = 0;
  SegmentTree<long long, long long> st(last, N);
  for (i = 0; i < (long long)(n + 1); i++) {
    long long y = st.getValue(pre[i], N - 1);
    ans = max(ans, max(0ll, y - i));
  }
  if (ans)
    cout << ans << " " << solve(s, n, ans) << "\n";
  else
    cout << "No solution"
         << "\n";
  return 0;
}
