1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <string>
// #include <ctype.h>
#include <algorithm>


using namespace std;

long long C2(int n) {
	return ((long long)n * (long long)(n-1)) / 2LL;
}

inline bool is_vowel(char c) {
	c = tolower(c);
	return c=='a' || c=='e' || c=='u' || c=='i' || c=='o' || c=='y';
}

inline bool is_consonant(char c) {
	c = tolower(c);
	return c>='b' && c<='z' && !(c=='e' || c=='u' || c=='i' || c=='o' || c=='y');
}

void update_result(long long &res, int i, int num_same, int &prev_bad_fragm_after_end, int str_len) {
	
	// fully in current fragment	
	long long add1 = (long long)(num_same-2)*(long long)(num_same-1)/2LL;
	// starts strictly earlier (but this the FIRST fragment making substr bad), 
	// finishes either inside or strictly after
	long long add2 = (long long)(i-num_same-prev_bad_fragm_after_end+2)*(long long)((num_same-2LL) + (str_len-i));
	// starts inside, finishes strictly later
	long long add3 = (long long)(num_same-2LL)*(long long)(str_len-i);
	res += add1+add2+add3;

	prev_bad_fragm_after_end = i; // the last in the function
}

int main(int argc, char* argv[])
{
	string s;
	cin >> s;
	s.push_back('!');
	long long res = 0LL;
	int num_vowels = 0, num_consonants = 0;
	int prev_bad_fragm_after_end = 2; // tak trzeba. dwa.
	for(int i=0; i<s.size(); i++) {
		if(is_vowel(s[i])) {
			num_vowels++;
		} else {
			if(num_vowels >= 3) {
				update_result(res, i, num_vowels, prev_bad_fragm_after_end, s.size()-1); // "-1" to avoid artificially added "!"
			}
			num_vowels = 0;
		}
		if(is_consonant(s[i])) {
			num_consonants++;
		} else {
			if(num_consonants >= 3) {
				update_result(res, i, num_consonants, prev_bad_fragm_after_end, s.size()-1); // "-1" to avoid artificially added "!"
			}
			num_consonants = 0;
		}
	}
	cout << res << endl;
	return 0;
}