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
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <iostream>

using namespace std;

// -------- STOS

struct elem{
    unsigned int dane;       // miejsce na przechowywanie danych zapamiętanych w danym elemencie
    elem* nast;     // wskaźnik na kolejny element stosu (właściwie to poprzedni dodany)
};

void push (elem* &stos, int x)
{
    elem *nowy = new elem;  // przydzielenie pamięci dla nowego elementu
    nowy->dane = x;         // wczytanie danych do nowego elementu
    nowy->nast = stos;      // wskaźnik nowego (ostatniego) elementu wskazuje na poprzedni (przedostatni) element
    stos = nowy;            // wskaźnik stosu pokazuje na nowy (ostatni) element stosu, czyli jedyny, do którego jest bezpośredni dostęp
}

int pop (elem* &stos)
{
    if (stos)   // sprawdzenie, czy stos nie jest pusty
    {
        elem *temp = stos;      // wprowadzenie pomocniczego wskaźnika
        int doZwrotu = temp->dane;  // zapamiętanie w zmiennej lokalnej, co trzeba będzie zwrócić
        stos = stos->nast;      // wskaźnik stosu przesuwamy, by pokazywał na przedostatni element (czyli ten, który zostanie ostatnim po usunięciu obecnego ostatniego)
        delete temp;            // usunięcie pamięci przydzielonej na element
        return doZwrotu;        // zwraca wartość z usuniętego elementu
    }
    return 0;       // zwraca 0, gdy stos jest pusty
}

int top (elem* stos)
{
    if (stos)   // sprawdzenie, czy stos nie jest pusty
    {
        return stos->dane;        // zwraca wartość z ostatniego elementu
        // nic innego nie jest modyfikowane!
    }
    return 0;       // zwraca 0, gdy stos jest pusty

    // w skrócie funkcja topEl może wyglądać tak, jak poniżej
    // return (stos ? stos->dane : 0);
}

bool isEmpty(elem* stos)
{
    if(stos)        // sprawdzenie, czy stos nie jest pusty
        return false;   // zwraca 0, jeśli stos nie jest pusty
    else
        return true;   // zwraca 1, jeśli stos jest pusty

    // w skrócie funkcja isEmpty może wyglądać tak, jak poniżej
    // return (stos ? false : true);
}

// -------- STOS

int main()
{
    elem *stosGrup = nullptr;

    char grupa = 0;
    int gdzieJestem = 0;    // do 200 000
    bool poprzedni = true;  // spolgloska

    char zyczenia[200001];

    cin >> zyczenia;

    // ------------ IDENTYFIKACJA GRUP

    while(zyczenia[gdzieJestem])
    {
        if(zyczenia[gdzieJestem] == 97
           || zyczenia[gdzieJestem] == 101
           || zyczenia[gdzieJestem] == 105
           || zyczenia[gdzieJestem] == 111
           || zyczenia[gdzieJestem] == 117
           || zyczenia[gdzieJestem] == 121)
           {
               if(poprzedni)
                grupa = 1;  // pierwsza samogloska
               else
                grupa++;    // kolejna samogloska

               poprzedni = false;
           }
        else
        {
            if (poprzedni)
                grupa++;        // kolejna spolgloska
            else
                grupa = 1;      // pierwsza spogloska

            poprzedni = true;
        }

        if(grupa == 3)
        {
            // ADD TO SEKWENCJA
            push(stosGrup, gdzieJestem - 2);

            gdzieJestem -= 2;   // bo sekwencje moga sie zazebiac
            grupa = 0;
        }
        gdzieJestem++;
    }

    // ---------- ANALIZA GRUP
    // gdzieJestem - dlugosc zyczen

    if(isEmpty(stosGrup))    // nie znaleziono sekwencji
    {
        cout << 0;
        return 0;
    }

    // znaleziono co najmniej jedna sekwencje

    // ostatnia (pierwsza od konca) sekwencja
    int aktualnaSekwencja = pop(stosGrup);
    int przedSekwencja = aktualnaSekwencja;
    int poSekwencji = gdzieJestem - aktualnaSekwencja - 3;
    unsigned long long wzor = 1 + przedSekwencja + przedSekwencja * poSekwencji + poSekwencji;

    // pobranie kolejnych elementów ze stosu, aż do całkowitego opróżnienia
    while(!isEmpty(stosGrup))    // dopóki stos nie jest pusty
    {
        gdzieJestem = aktualnaSekwencja;    // ustawienie dlugosci na poprzednio policzona sekwencje

        aktualnaSekwencja = pop(stosGrup);

        przedSekwencja = aktualnaSekwencja;
        poSekwencji = gdzieJestem - aktualnaSekwencja - 3;

        if (poSekwencji == 0)  { // sekwencja xxxyyy czyli grupa spolglowek i grupa samoglosek obok siebie
            poSekwencji = 2;
            wzor = wzor + 1 + przedSekwencja + przedSekwencja * (poSekwencji) + poSekwencji;
        }
        else    {
            if(poSekwencji < 0) // jeśli sekwencje się zazębiają
                wzor = wzor + 1 + przedSekwencja;
            else    // jeśli sekwencje się nie zazębiają
                wzor = wzor + 1 + przedSekwencja + przedSekwencja * (poSekwencji + 2) + poSekwencji + 2;
        }
    }

    cout << wzor;

    return 0;
}