muzicari

Dva muzičara su osmislila po jedan riff (niz nota). Da bi odlučili koji je bolji, dali su oba riffa poznatom bendu koji ih je ubacio u novu pesmu. Riff koji se pojavi više puta u pesmi smatra se boljim. Ako se oba pojave isti broj puta, smatraju se jednako dobrim.

Opis ulaza

Sa standardnog ulaza unose se tri niske:

Opis izlaza

Na standardni izlaz ispisati \(1\) ukoliko je bolji riff muzicara \(1\), ispisati \(2\) ako je bolji rif muzicara \(2\) i ispisati \(0\) u slucaju da su jednako dobri.

Primer

Ulaz

ABCAB CABCA ABCABCABCABCAABCAB

Izlaz

1

Rešenje

Opis glavnog rešenja

U ovom bloku se opisuje glavno rešenje zadatka.

#include <string>
#include <iostream>
#include <vector>

// Funkcija koja na osnovu uzorka pattern racuna preffix_table niz
void compute_preffix_table(std::string &pattern, std::vector<int> &preffix_table)
{
  int n = pattern.size();

  preffix_table[0] = 0;

  // Indeks i je indeks koji ide kroz nisku, a indeks j ce zapravo sluziti da kaze kolika je duzina prefiksa i sufiksa koji se poklapaju
  int i = 1, j = 0;

  // Krecemo se kroz nisku
  while (i < n) {
    // Ukoliko poklopimo odgovarajuca 2 karaktera, potrebno je da na poziciju i smestimo j + 1 sto nam zapravo kaze kolika je duzina sufiksa niske
    // pattern[0-i] koji se poklapa sa prefiksom reci, tj kaze nam od koje pozicije u niski text nastavljamo pretragu ako nema poklapanja teksta i uzorka
    // na nekoj poziciji. Ako smo nasli poklapanje uvecavamo oba indeksa
    if (pattern[i] == pattern[j]) {
      preffix_table[i] = j + 1;
      i++;
      j++;
    }
    // Ako nema poklapanja na pozicijama i i j
    else {
      // Ako nismo na pocetku niske menjamo vrednost indeksa na LSP[j - 1]
      if (j != 0)
        j = preffix_table[j - 1];
      // Ako smo dosli na pocetak, na LSP[i] stavljamo 0 jer nemamo nikakav prefiks koji je i sufiks, i uvecavamo i
      else {
        preffix_table[i] = 0;
        i++;
      }
    }
  }
}

// Funkcija KMP koja implementira KMP algoritam. Kao argumente dobija string koji predstavlja text i string koji predstavlja uzorak koji se trazi
int KMP(std::string &text, std::string &pattern)
{

  // Racunamo duzinu teksta kao i uzorka koji se trazi
  int m = text.size();
  int n = pattern.size();

  // Kreiramo LSP niz, njegova duzina je n jer je usko povezan sa samim uzorkom koji se trazi cija je duzina n
  std::vector<int> preffix_table(n);

  compute_preffix_table(pattern, preffix_table);

  // Indeksi koji se krecu kroz tekst (i) i uzorak (j)
  int i = 0, j = 0;

  int counter = 0;

  // Idemo kroz ceo tekst
  while (i < m) {
    // Dok god mozemo da poklopimo karaktere, to i radimo, i samo uvecavamo indekse kako bismo se kretali kroz tekst i uzorak
    if (text[i] == pattern[j]) {
      i++;
      j++;
    }

    if (j == n) {
      counter++;
    }

    // Ako nismo prekoracili duzinu teksta (moze da se desi jer gore uvecavamo indeks i) i ako se odgovarajuci karakteri ne poklapaju, premestamo indeks i
    // koji se krece kroz tekst da dodje bas na poziciju preffix_table[j - 1], jer znamo da odatle treba krenuti u dalje poklapanje zato sto je sve pre toga vec
    // poklopljeno (sufiks je isti kao prefiks)
    if (i < m && pattern[j] != text[i]) {
      // Ako se nismo vratili na pocetak teksta azuriramo indeks j i gledamo odakle uporedjujemo dalje
      if (j != 0)
        j = preffix_table[j - 1];
      // Ako smo se vratili na pocetak teksta i nema poklapanja idemo dalje kroz tekst
      else
        i++;
    }
  }

  return counter;
}


int main ()
{
   std::string riff1, riff2, song;

   std::cin >> riff1 >> riff2 >> song;


   int counter_1 = KMP(song, riff1);

   int counter_2 = KMP(song, riff2);

   if (counter_1 > counter_2) {
      std::cout << 1 << "\n";
   }
   else if (counter_1 < counter_2) {
      std::cout << 2 << "\n";
   }
   else {
      std::cout << 0 << "\n";
   }

   return 0;
}