#include <iostream>
#include "poszukiwania.h"
#include "message.h"
using namespace std;
typedef long long llong;
template <class T>
T pow_mod(T x, T n, T Mod)
{
if (n==0)
return 1;
else if (n==1)
return x %Mod;
else if(n%2==1) //nieparzyste
return (x *pow_mod(x, n-1, Mod)) %Mod;
else //parzyste
return pow_mod((x*x) %Mod, n/2, Mod);
}
class parametry_hashowania
{
public:
llong Baza, Mod, Dlugosc, Baza_max_pow;
parametry_hashowania(llong baza, llong mod, llong dl)
{
Baza = baza; Mod = mod; Dlugosc = dl;
Baza_max_pow = pow_mod(Baza, Dlugosc-1, Mod);
}
void zmien_dlugosc_sygnalu(llong dl)
{
Dlugosc = dl;
Baza_max_pow = pow_mod(Baza, Dlugosc-1, Mod);
}
};
template <typename F>
llong policz_hash(F getfun, llong start, const parametry_hashowania& param)
// hash = c_1 *Baza^(dl-1) + c_2 *Baza^(dl-2) +...+ c_{dl-1} *Baza^1 + c_dl *Baza^0
// liczony w arytmetyce modulo Mod
{
llong hash=0;
llong Baza_pow = 1; // Baza^0 %Mod - w kolejnych krokach wyzsze potegi
for (llong ii=start+param.Dlugosc-1; ii>=start; ii--) // sumowanie od konca sygnalu -> najnizsza potegi bazy
{
hash += (getfun(ii) *Baza_pow) % param.Mod;
hash %= param.Mod;
Baza_pow = (Baza_pow *param.Baza) %param.Mod;
}
return hash;
}
llong przesun_hash(llong hash, llong start, const parametry_hashowania& param)
// start - indeks poczatku ciagu w dotychczasowym hashu ; Baza_max_pow = Baza^(dlugosc-1) %Mod
{
hash -= (SeqAt(start) *param.Baza_max_pow) %param.Mod;
if (hash<0)
hash+= param.Mod;
hash = (hash *param.Baza) %param.Mod;
hash += SeqAt(start + param.Dlugosc);
hash %= param.Mod;
return hash;
}
int main()
{
llong S = SignalLength();
llong M = SeqLength();
llong Baza1 = 1, Baza2 = 3;
llong Mod = 1000000033; // 10^9+33
parametry_hashowania param1 = parametry_hashowania(Baza1, Mod, S);
parametry_hashowania param2 = parametry_hashowania(Baza2, Mod, S);
// indeksowanie od 1!
llong hash_sygnal1 = policz_hash(SignalAt, 1, param1);
llong hash_sygnal2 = policz_hash(SignalAt, 1, param2);
llong hash_tab1 = policz_hash(SeqAt, 1, param1);
llong hash_tab2 = policz_hash(SeqAt, 1, param2);
llong licznik_trafien=0;
if (hash_tab1 == hash_sygnal1 && hash_tab2 == hash_sygnal2)
licznik_trafien++;
for (llong ii=1; ii< M-S+1; ii++)
{
hash_tab1 = przesun_hash(hash_tab1, ii, param1);
hash_tab2 = przesun_hash(hash_tab2, ii, param2);
if (hash_tab1 == hash_sygnal1 && hash_tab2 == hash_sygnal2)
licznik_trafien++;
}
if (MyNodeId()==0)
cout<<licznik_trafien<<endl;
// po zebraniu czesciowych hashy z instancji - pamietaj zmienic Dlugosc w parametrach_hashowania!!!
return 0;
}
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 | #include <iostream> #include "poszukiwania.h" #include "message.h" using namespace std; typedef long long llong; template <class T> T pow_mod(T x, T n, T Mod) { if (n==0) return 1; else if (n==1) return x %Mod; else if(n%2==1) //nieparzyste return (x *pow_mod(x, n-1, Mod)) %Mod; else //parzyste return pow_mod((x*x) %Mod, n/2, Mod); } class parametry_hashowania { public: llong Baza, Mod, Dlugosc, Baza_max_pow; parametry_hashowania(llong baza, llong mod, llong dl) { Baza = baza; Mod = mod; Dlugosc = dl; Baza_max_pow = pow_mod(Baza, Dlugosc-1, Mod); } void zmien_dlugosc_sygnalu(llong dl) { Dlugosc = dl; Baza_max_pow = pow_mod(Baza, Dlugosc-1, Mod); } }; template <typename F> llong policz_hash(F getfun, llong start, const parametry_hashowania& param) // hash = c_1 *Baza^(dl-1) + c_2 *Baza^(dl-2) +...+ c_{dl-1} *Baza^1 + c_dl *Baza^0 // liczony w arytmetyce modulo Mod { llong hash=0; llong Baza_pow = 1; // Baza^0 %Mod - w kolejnych krokach wyzsze potegi for (llong ii=start+param.Dlugosc-1; ii>=start; ii--) // sumowanie od konca sygnalu -> najnizsza potegi bazy { hash += (getfun(ii) *Baza_pow) % param.Mod; hash %= param.Mod; Baza_pow = (Baza_pow *param.Baza) %param.Mod; } return hash; } llong przesun_hash(llong hash, llong start, const parametry_hashowania& param) // start - indeks poczatku ciagu w dotychczasowym hashu ; Baza_max_pow = Baza^(dlugosc-1) %Mod { hash -= (SeqAt(start) *param.Baza_max_pow) %param.Mod; if (hash<0) hash+= param.Mod; hash = (hash *param.Baza) %param.Mod; hash += SeqAt(start + param.Dlugosc); hash %= param.Mod; return hash; } int main() { llong S = SignalLength(); llong M = SeqLength(); llong Baza1 = 1, Baza2 = 3; llong Mod = 1000000033; // 10^9+33 parametry_hashowania param1 = parametry_hashowania(Baza1, Mod, S); parametry_hashowania param2 = parametry_hashowania(Baza2, Mod, S); // indeksowanie od 1! llong hash_sygnal1 = policz_hash(SignalAt, 1, param1); llong hash_sygnal2 = policz_hash(SignalAt, 1, param2); llong hash_tab1 = policz_hash(SeqAt, 1, param1); llong hash_tab2 = policz_hash(SeqAt, 1, param2); llong licznik_trafien=0; if (hash_tab1 == hash_sygnal1 && hash_tab2 == hash_sygnal2) licznik_trafien++; for (llong ii=1; ii< M-S+1; ii++) { hash_tab1 = przesun_hash(hash_tab1, ii, param1); hash_tab2 = przesun_hash(hash_tab2, ii, param2); if (hash_tab1 == hash_sygnal1 && hash_tab2 == hash_sygnal2) licznik_trafien++; } if (MyNodeId()==0) cout<<licznik_trafien<<endl; // po zebraniu czesciowych hashy z instancji - pamietaj zmienic Dlugosc w parametrach_hashowania!!! return 0; } |
English