Neka su date dve binarne niske \(S\) i \(T\). Prebrojati koliko postoji cikličnih permutacija niske \(T\) takvih da sa niskom \(S\) primenom operacije XOR daju rezultat 0.
Sa standardnog ulaza se unose 2 niske \(S\) i \(T\).
Na standardni izlaz ispisati broj cikličnih permutacija koje zadovoljavaju navedeni uslov.
101 101
1
Zadatak se svodi na rešavanje sledećeg problema: koliko rotacija jedne niske izgleda isto kao druga niska?
Umesto da posebno pravimo svaku rotaciju, koristimo sledeću ideju:
ako nisku zalepimo samu na sebe (bez poslednjeg karaktera), sve njene
rotacije se pojavljuju kao delovi te nove niske. Rotacije početne reči
možemo pronaći tako što gledamo prozore odgovarajuće dužine kroz tu
“dupliranu” reč. Na primer, za reč abc, “duplirana” niska
bi bila abcab, a njene podniske abc,
bca i cab su rotacije polazne reči.
Pošto ne želimo da pretražujemo naivno karakter po karakter za svaku rotaciju, koristi se Z-algoritam za pretraživanje niske.
#include<iostream>
#include<vector>
using namespace std;
vector<int> calculate_z_array(const string &s) {
int n = s.size();
vector<int> z(n);
int l = 0;
int r = 0;
for (int i = 1; i < n; i++) {
// Ako je tekuca pozicija unutar opsega [l,r] koristimo prethodno izracunatu vrednost za inicijalizaciju
if (i <= r) {
z[i] = min(r - i + 1, z[i - l]);
}
// Preskacemo proveru karaktera od pozicije i do pozicije z[i].
// Poredimo karakter po karakter u niski i sve dok se karakteri poklapaju povecavamo vrednost z[i]
while (i + z[i] < n && s[z[i]] == s[i + z[i]]) {
z[i]++;
}
// Ako je nova vrednost desnog kraja intervala poklapanja veca od prethodne vrednosti, azuriramo interval [l,r]
if (i + z[i] - 1 > r) {
l = i;
r = i + z[i] - 1;
}
}
return z;
}
int main(){
string s, t;
cin >> s >> t;
string t1 = t + t.substr(0, t.size() - 1);
string s1 = s + "#" + t1;
vector<int> z_array = calculate_z_array(s1);
int counter = 0;
for (int x : z_array) {
if (x == s.size()) {
counter++;
}
}
std::cout << counter << "\n";
return 0;
}