From b9645f15ff8956732f796d1f45fe4873002ae528 Mon Sep 17 00:00:00 2001 From: Knyffen Date: Sun, 14 Nov 2021 18:13:51 +0100 Subject: [PATCH] Better string handling The text and pattern are now streamed directly (skipping saving them to strings). Knowing exactly what string was matched has now been delegated to the Rabin_fingerprint_process. --- README.md | 13 +++++++++- V1/simple_string_matching | Bin 58864 -> 58912 bytes books/pattern.txt | 1 + processes.cpp | 36 ++++++++++++++++++++++--- processes.hpp | 3 +++ simple_string_matching | Bin 92408 -> 77768 bytes simple_string_matching.cpp | 52 +++++++++++++++++-------------------- 7 files changed, 73 insertions(+), 32 deletions(-) create mode 100644 books/pattern.txt diff --git a/README.md b/README.md index 7c8d1c7..1c41f2e 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,20 @@ Code used for my Bachelor's Thesis +# Issues +When reading the pattern from a file, according to UNIX standards ([read details here](https://unix.stackexchange.com/questions/18743/whats-the-point-in-adding-a-new-line-to-the-end-of-a-file)) a "text file" has to end on a newline. +This adds an unintended newline to the end of the pattern, so to avoid adding said newline, write the file using: +`echo -n word > pattern.txt` +or if you use Vim, remove the newline using +``` +:set binary +:set noeol +:wq +``` + # Versions ## Current Version -Compared to V1, this current state `generate_initial_irreducible_polynomials.sage`, `generate_random_irreducible_polynomial.sage`, and `multiply_polynomials_modulo_polynomial.sage` have been removed from the main folder, as they have already been used for implementing their corresponding features in `general_library.cpp`. They will be preserved in the V1 folder. +Compared to V1, in this current state `generate_initial_irreducible_polynomials.sage`, `generate_random_irreducible_polynomial.sage`, and `multiply_polynomials_modulo_polynomial.sage` have been removed from the main folder, as they have already been used for implementing their corresponding features in `general_library.cpp`. They will be preserved in the V1 folder. This version also contains code relating to Porat-Porat and other random code stumps. This code is going to be completely reimplemented, but is preserved for now to avoid redoing work. diff --git a/V1/simple_string_matching b/V1/simple_string_matching index 54fb4194b3c44f878e895505cd0c1124ad79bf90..03d91983d1f482fab97e2c9c406d52bedccc88af 100755 GIT binary patch delta 13484 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 delta 13576 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 Pk`>?WqaI_A?soVeYnWd# diff --git a/books/pattern.txt b/books/pattern.txt new file mode 100644 index 0000000..387155e --- /dev/null +++ b/books/pattern.txt @@ -0,0 +1 @@ +word \ No newline at end of file diff --git a/processes.cpp b/processes.cpp index 3f53510..ec18695 100644 --- a/processes.cpp +++ b/processes.cpp @@ -5,14 +5,14 @@ Rabin_fingerprint_process::Rabin_fingerprint_process(uint32_t irr_poly, size_t w phi(irr_poly, window_size_in_bits) {} -void Rabin_fingerprint_process::stream_char (char c) { +void Rabin_fingerprint_process::stream_char(char c) { std::bitset<8> b(c); for (char i = 7; i >= 0; i--) { stream_bit((bool)b[i]); } } -void Rabin_fingerprint_process::stream_bit (bool b) { +void Rabin_fingerprint_process::stream_bit(bool b) { if (window.size() == window_size_in_bits) { window.push(b); bool b_out = window.front(); @@ -24,6 +24,36 @@ void Rabin_fingerprint_process::stream_bit (bool b) { } } -uint32_t Rabin_fingerprint_process::get_fingerprint () { +uint32_t Rabin_fingerprint_process::get_fingerprint() { return phi.get_fingerprint(); } + +std::string Rabin_fingerprint_process::get_string_in_window() { + // check if window contains a whole number of chars + if ((window_size_in_bits & 0b111) != 0) + throw std::logic_error("The fingerprinting window doesn't contain a whole number of chars (counting the bits), so it doesn't make sense to return it as a string."); + + #ifndef NDEBUG + if (window.size() != window_size_in_bits) + throw std::logic_error("False match! The sliding window isn't even filled yet, which means you matched the pattern of a substring shorter than the pattern. This case should be handled/avoided elsewhere, so we throw an error."); + #endif + + std::ostringstream os; + for (size_t i = 0; i < window.size()>>3; i++) { + // cycle the char + char c = 0; + for (size_t j = 0; j < 8; j++) { + bool b = window.front(); + window.pop(); + window.push(b); + c <<= 1; + c |= b; + } + + os << c; + } + + std::string s = os.str(); + + return s; +} diff --git a/processes.hpp b/processes.hpp index 05561b1..a412d32 100644 --- a/processes.hpp +++ b/processes.hpp @@ -6,6 +6,8 @@ #include #include +#include +#include class Rabin_fingerprint_process { public: @@ -13,6 +15,7 @@ class Rabin_fingerprint_process { void stream_char(char c); void stream_bit(bool b); uint32_t get_fingerprint(); + std::string get_string_in_window(); private: std::queue window; diff --git a/simple_string_matching b/simple_string_matching index 4dd651934aaa81dbd90e6ec3c046fabc43570e38..2140c26b723881ef59b920e0120459839ba072c1 100755 GIT binary patch delta 26186 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 literal 92408 zcmeFa3wTu3)%bmKgNR6?qD4g+?;sb$MFi9uguy{TBNs~*4FQ5gLlSdAu%gj`Wg4PU zK~b@#mHMLfRcg^v>m?v{s6~y6nks6n)J_C#w5X{?^Z%{A*Ew@$GGkl6|MNZH_dJeI zSZA-b_S$Q&+umoNGvoEa$rIAk(j51b;e6kb*2ZBLldpu1*)g7cXOwf0lkWtaeoi;& znf$qYiLfOdA|DrK+oqENlzx5WA_?qk(T)q<(FIDsRGXzo%TzBJH}YN3;q4XHlyCQ^idzh!)-c=R-+U&)lo|%17HhvmI9~Z(C}YTH+Fz^ZeVg$Lv|s2xD<=`o>tXRO zbjQ1peqxvZ^rPlfh`d{@RG!&RW*{fw@n;^w8|~_2<=|zhcWRO9xK8fAABhJ~8;TH~#1T&qiEz@1sAy z=z+$DdrONaP5AhplB;gZ>o~Cctz$+`eqqF<_Jc-GYJcLG!~fai^zM!CPrkps_nMyL zew2OB*Zm)RW!+(qv{bzR)_`lbzWm4QzRtUS%Fn;oy(dGb{2bcdaSlmBEyBOa@Vg17 zWcU{kOpc$8fs^sSjsuh7m!#m&WERII(X%bZxStR}$>d*|VqQ}T$YlII2%=>8pQq4s zKY5sp|CcHByfTG7ze>U1o&q0Dq35e9_+L+<{|hPj11aKURSNv%6n6eo3OkQWq0jUb za#~X8xr!J`X8$u%jQe(qaqB1wN#&%#4^9zpcc-w=p~Q1C`M*pNKUb#Ee|if2pGaXJ zsf&RmdGvG&{!>!K=c*L>dsK>f5uQoM9h3q;FvYy?!_LP!y_{>t+DVMoxzxjdtaG?i ztLuIr#otf-2>)U!#(cVoB7CNzzu*U*W7|hr;5-an@Ux|`^EuH1=L`HO_Pb<-~)?-+8u0%v5}To$u$W&yk9sNL~p4 zC>{4?#ebsXCgNq9!oN}#ao5(hDkr4&ELS-n;a}k&uj9J>e?$L+9lZCcWz0oC`P_ni zBpzlb#KZe4f0N2_?R=@)t%us*_16(JUgBO=RWmIZA3T93JWh^SYB3GRb5nBU0CQ8PMkiaa9(j`@#Q5|)y0+5r;IBtFDss2G^e!K(vnjy zK7U&E>4k-J7cU+u z9bP!CaBg|Ul0uXg%({{Tv=IOiCQB4zZZUbA+{{4E@Eom zPQcKiNSIqxQ8c%tdP#8Mw-Zvb*z`0uP3epzmYrTWJrCQSUO079>bXxFQHb@Y4=oG^ z(QaO8!6K`rczFC!W7hMhm6ukj3L}ck=9MN3iDa%-1x89lq}Cwil!guy3KRS(OXUtW22QRTeC5~94Qx}4}Ny8K&?lP7L2W|;DC?W56%&`4A- z4;^9Sykx!`=t=Tn+|Z!p3`tQqvAnAAf{Nm@h2`_eRI%64;gvOI)g=pyZ4_JHZ#Tv9 z!_<@2qe>VD&5B1%EGwyw^Kik0sng1*6%q&3fg+nn42L3A2AfrLisls-m6n#zCEX0u z9O_IN5nera0j$#{=i{~3shsAO6mot}&HSVxG_q<=&BBVgMpcPK(^mp<+_2!(Nz=Z4 z7>yN`3m2477ZFu37h%Iy+R&k;<(E_JOrfymFcUMgEUL!#i{}FOQOXrlP_KAn!)Sg+gUz(UQWlVz=Ci$4m_PjruK3%e>-Azd)zKKL>}st7@##hi>umnpwf1yfYV9KXEf*3gQgiWlb#ZX&LS&dg zuPipHZF23u-U4{`W{cp#5PAbZ;b_!>dU0s4%rWRM#EG%}aDvQeIIkM!_g&qCeE7@9KSvbF_ zq|~8OlMyP46kc3X?JO)_IJaVnE51ZlrE7`>yRdwbh~O+$w()Xju&}74%%NRXJ#X&7 zfpVTYQko0BtIOxYDy^Y{pKI~wjvH4vd`O;i?&OK*j4K>AWY}o$a)fs^G`$Z5{F znKQ?pGqG^!kl{m=d*)1pjF8STn(ggUhWeY_;G~=XGWa)>lim#e6HJ!*S70}%JGe}P zx3p}f9iUM9NuLa${KxH?bD(164vKSO^T&DdfAF73^7F~raGEoLvkLb-q~N3_-029OO6$I9DldmErI1{7Bn1N0xA>n&I5! z_0Mt!D^12*^712$pY7bHxFsETa&pnl`I)v~eMC-xvYdyteU+hSI=|C)^?=*BvrTul z)0U6>+ytcgtdj$5KKXh-?Bb8s=P;oJ{J%;pe?bENm=zX3GXY8^aYz2WZ` zj}g6RD1zDO!(#yNv)PAt&t`Y~n|=6GefSn1KF^15_2Gy5@KGOr zm=9l}^Oa+V{yw~W?ts%A_iRAO?)jA9-Lo9QyXO~zpJ)*FpFZsta(qBU#y$ZboKG--j2Uxu1{^FFLuO0w110_dYXyc*$Y+GuwyPkTs+Q zKKwy0GqA#kch78uyx51&@$uLC@VP$x3LoA*n-OxO5AUAI34VJ-C*&3%-hC!4_*NhOXhG;F z>chKdU_xs5;rqGFzz!e&SRdZeypR|<&WF$T;g9#>bA9*|eE2>-{E0q%z=uD{hwtyh zpX|fu`S1gL_)$LmDL#C@4?oC<5BczeefR<&euxkM-Q{-{_|5{~S>QVhd}o30EbyHL zzO%r07WmEr-&x>03w&pR?=0~DUkm&r=a?@;b$hcz^;v&>#&JT+o2t`0n?rTmvY$1R z>OAc)pgT|8&A&PQ^0|`s0-?3FcJev#O=-)KUR$$izanip%4=&f?dPQ}M|f=;O?#`f z<>;<$ooPQIZ8@@QYc%agr7cHwZMCNTptR-qrLDrWe<5u-mTjAD+ILG^j_TS9O#3!z z%Mo2$zG?qN+Hxe@mS@^GN?VTV+5)D1jkM*6t}WNJE2S+*b8U`kUmH$4Fa_*xDLRdziH4 zXsxZ*v`>+?9I3TcnD%kfmZP+`*`|G@wB-n`t-!Pok+vM2wdI?34{6KMb6cKir%PLo z(Aol~{pHiN<>;&}*R(&Cwj7zYIi~%gwEIcB{VSROU!)z7cB^T>DQ!72Yil;`SEMaR zWo=ES{k*j0h^%d+X>XOb9F4WDGwmm&Ek|N)ji&vmwB;zQt=6<3l(rm!wN=oTcpduD z#PG|Pg~ERc)$MLCm_E57>$%Gb-G+lMFyO3viN?;uK7G=0_BDnY&N_k#hZ?fPE}_vK z)rS%4FG7=0KcKTUr(Z3yoo5xo-^PHUhSOx8p#fiq!tJ3gADaRCm@na5|yzU#kxa)t~kGQ=(ZOsOVg5`CQgY z7}G9&cK(o@e#=A+=h^wOYsoi}*LFF)Gmt@|=7qvbqoHt3YbZRUg;|X+73t4$HB9sk zN1_j6rBHZls6GhabD{7X(V6=#rXg#Pa)YcBwn(r;2Hi6W2+*u>up!3g|5n8rUo zD|49^x?!)Bg?XX+%oF8_Lns`K4n@%NR+yfU1jnPRjnEfm)K5iP!}2v|GLh)3wwWgY z>ItYCYFI6OVQMl=X2?GvX|i^!Z!qljPmL0``o|1g{p#()-LQNe$SL716T=-M@SpVa z4Y$hjxWmmbF^|WxvSu&ieZmGEH&Ta)}>C`RZSy$YCcvAx)$2 zQI_>BkM&|@eMMNqTV-}KoOSI|+y8^#dHvrqn5>-!BSRgj{kKARrXOaF-gBzsgqQ1# ztguM5o)R0{(wY$pFW)FC)UOs$-{7**2pd1Fy8uR4iRGIOuLaEK2AOx*I;q~nK5MaJ zjXh`kjQS(WKJm3;`Rz!_d3v<~5iMgGW307fxjr8VKTcMwTdd)eZvoV`r!8x$`FWz^ z!fX})+xhg4EMJFotl;b!1*1;+gL^P>0ozp}`(;*U_0e5J$ zLFe4o#Q49`UgF&I3$XLE!Y!kKI19w+XLDA;SUtceB}b%$w}7#VYz>89lnUZRyIK9* z;XV)pgqLps+qMBZGmvYqqfs?%t(x<6{0s_Y`gTg9%deSGoO0q%%`|k< zvkitqVH61sV4RQ`#Z&&BQ23?jBniYi!xAG#qQ^_;(FScSmb3hHsv9NsxZld$Bw`ns z*o{PU|0z?;dQGajAzYw@NQd+|to?Bzm^uFy3}uFPY=-jSS>~a}U!hH%#2JK)r*kAa z$TnM*dfFF6O^Z~;d7**5O?}E)wi@|u^)iStoEw!(7<lO=cOgyeT3hW`j z{1NdFmMRaYWB;70=+o>r+jKR%=X2(cY7ElEAkhQ)CscoFhpnot5V_%{`@=OIbxZfB z)tqs|QphYt!?5FVYQ53Yqao`GV{ht7)&W{8>a$*dOePnJ9?tZ&PCqUEpOO7t^d1~_ zsVUx@X*%|j^@w^|(;li1w&y&a3+Pyp+o-g9a7} zRxVT1QJIJIw35TDO?6A7PE9wFz9&Dr1Vs>Ygk80!$k=e2>eNe&d<=vRknN%H%Mv+8 zK1uabbg*v-5l_eZt`q5~mwB|;JEOOftU6`J)Y%)w#Ik6Ab?#=~R&c1_Sni9Ojy+kM z#a5R-+o%h6uHiNcMxw9aOJR~<0YT_M7v~Wu>QoY&Zw9nbQ99zU${G1xFbRH2z5^uTZ8tr z=YoHyIxA{tUJ-v*6P;{5m$LRR-F|++y)7Fi#|ruw`fNPk+yhg1Cw37TlAp=Ww5R!jihXbc%7pOSiM|EE4Lk!*hN zo+33wJ>7&D&zmlvO%p;j5?y2TLyNR#cO=hK`PqrS@i6g{m;;Malpw$!vT+k}BK>u= zH1i6lN6(hBf|0}LWTQ}*sEkPDI?*G#a7omSvgRj`sIs53Lqj@#2ydUvY88GSL=y;F zQ(7^$>>y2AzaXU+4&yIb%tGOJqpu6Heo9lQe(Cm5eND4QM^yJ)Kg4)@j`X?pI_^HS z(7o{wnS#_f;}g*=AuwWNU+9f(qrr@Qu^{V~wmP!=w+S=L?2~4+VzE8k{erBEk{*&^ zQ<#LQ7I)&LIGsK;B^tqz=(w&rEx=l9{AnTk+4|rbVSi9!LrOmutDgbNEL-!dY2aecrBC7!Z10qK$G7Q{^qZ^J5}BhmFDJys%C)11uxqSS^+^f5z} znnYKl%&mf{+ZMQF>@2r(d)b(@me)1qiX_QmFQ-JW4zm=>g5};&*#VZf%dDi#lJeo) zE|o#6MjqBPwXynpmb)O=Kr5st-tl_I878(uXaX@k8cY>%we_jxt2=J3 zG71;SiXK}};%V6)&F33`c*yEdPo^2&jJ+R4z2|~oNJNusk?2n(*M-Hb6kq5{aj)z` zWd8m*KkDxiif(OAV)MA|KoAGTs$QP;kd1aJXT%Dw@|Ck@8&gx7sZy*rQVqnH!49ob zGvegs8hPrwpIDNsS&T+;=BQz;ND0;FhggQC-f$i2Z=l_{{DAHj?UF5*rQYCDG1m2V zX^E@kx&cGBKVW{Zy<+yVTE)2YtOmv@4GG+F5k}q>Fk6zkrU@Hu4uz*|Oz?3RS5LJ>Al+A;~OXP~qtnx)+*{(cM;_iN!9(P$onaa@)TL0aE_rvTGd#*TC*} z)C?1eHbZhfn?UMic5{*F?`68O(|S4TrD(u&jPZd?P4Xt#5p85Mp!bU?9f`gZ<+hsJ zzA1Pt*lusStVu_4d==9wABio@vYAG=)# zw=bnM$W4Ts25+$Z8ogtvcMM86xW_OD5p41$>qS$}nqP{JlAVTocV)+aFWE9a9X&m> z1&l#8DCJf^t%iL%J0)XdW3^jZ_V=(U>JpAGLQvO8O`nMt6gGsaw{vMH_0@#m$lMH!5}1VHPK}s=?H!XJNbwTS#H~Y3>}6bwxe6F@adl%IH@e(W#rz%+ zoA}e;+@08x_5jS`;6Bn|pLpwav(<~g6JGllU){=;*@$7x0Zb%%%X>uUOWG@ZPPUM| zBKMy~%uiYRb;UCg^CTjZu1VjMaQ5O^_3%7zHM7?3khy%Hsl{<`7XR_N-s>Zlf!A&g z%&h1qr;?Pdb~eH}k2i56le4-B{j#FNTO|p_F>I?*GUkc|Ip+QeHdAE=!|4kR6I0%q zP9JfN30Je?M51ywW$I9?jKV3kGb(nxsfj3~NdQOd^RvUj{cN-> zJ8LG<5y@vgw^cBbFVAG1dbEIG-6^jrpoG|;85s|c1{I41GhZY>-4FCLGSlcvBz_vo z8Pvos@c7`qu&LAGf=o9$V~0E~roK{}>hm*~H`Sc+Os@3r@eUIwDjKqK<%yPTJKl|+ z#(YBcSs$+zj6Bm=cDF}cVran@CO{I%8XpBXd#0f^qOONEax&9m_uit|P|@FXHuYG-?~Gt`<$Ze&m-{YMyZi0V&dK3cad?hs;vO^k7Lx7Z z_7%Zx32qPNJUwF@4#x_{u<}b)&jsJ;zGsq9-hk4|)&Q!h+fP6>D2Ca~b!SwjrIf%R7e->6;shO^`mS&!omSsq7c8}Z)BlBl>FzG%H;4Hh*ww$b|BoX3N^ z4-hN3m_9xO{uG}l7*LL2>1O^_`_U5}lHAkAM$ONTg+TXRZV1#&_S`%Soe6~k!i=fpm-R)El_K%%ye8)<-)@$F1+P54bqF1KDc+hk3`q{IyB0)edIVrERXyACvsto<~yBd6K=C!jkIrtJQ(y>jrCvgwEuCtOxpnM z#&*@sf3pe^kI5cLQES>mT@H@wTF>?tF*7t8cE}{&U{+6{yu-7IS2_J{j#Y89&cPPz zXdj!-&-r`Pr#YttJGgj-iy8aphjOlKo}bfyI~Qe5(KDE>pqflmE4!B^cJ;bc3Sz5h zAn$=`iITU^d_nF`lU3EzAz+Z+3M_RsZp$-Kq@lFCp0HlKt5Hk?ydw)>eIM}?2aegI z$2)RAaBPcRzhjw(uM);7h!0*MsJeXY5}JlIPiX2u6y*s#PAX4th~GG2>U06wCh7V9~%QLOX4!?Ce5>`X&=iA=587@qNvKl@vTHbsIvn6<-Qq|81N z+$k+Gc_(YZ*rxsccj%{y2E2-AS0v@ zA>lrC=)7lK-O?RSbw7H`5l!4sqv5J&cf4cIG0B7+=?Ovp8Nr8gR+dOf8DUF`netUE z-&#hxwOF5-*+!xV$vka=*=rmZ4yV8Xf+`HI=`vBQ0l@eJBj_L6FPdG6#L4`3lq>YR2O( ze}yQq!YHx6-XJH3cf%x!V&6}yKH95dC%@`dv9)+O`ZwC4hT>L9p3BA-#>ZUUw%YJh zGOO@oi{;XDVDdYpnG4|baK6Zx%8&pQ`+WX(~gBGI<}u-Jnx3Cs-=Y_Z6hO$Q=Jj4T%Y#>n}-FLM6z?;^)cRU$`@2An--G4whw za!jnmnwgFD#vI`nnbI`Tx1L8|^;6b`Gk=0p)`?Rjp*B?hE)rZR^6FR1>~M3VhDFYS zCM?*CGFXv@#Tvo_1``%HO58}aFvKRVyM)Ez-L3{aOr?!Pt6*P1K@@%qw2e z1B6A=M8tLxut#F0{!n(fNjvW_WLtNH#hS!s(2BOl2tO>dB7VR%(kGc^4itiG3$9lz zmp9T~Og}I=j~f&V-m+;)WuKW!_9J}#LL~7DrjXS|*ZgP*(B%1A`|>t+3amFhxjytk_l~uA;bc?X=CXep^QmU$!h0_1u_{cacmT z`jX=vre-EE2o8T8GROl#E_*9y*}sr%%1k)8q3vzc;E6}v2*-INi07#6W`s3%1Y?%x zxfahcd|c0{@OZkpJuma=*2uNbZ3!c9@cN6}-2TVd{_3{%+7h>owAW^Wr`T(wpXpH- z+#uy(gJxvVY}=woGZnEKAbKn#A*|kXr3yVQ@fY6m>IdQWhS1mHX0w(1 zf>VIHCS;iP-15e66C0_Qd1BYd@=*X}{NGsY*LYj8f!KRRcuW0inMJ+P!>pPe^1#c) z-;@=0Id}J1Wl?%ipotI@(El_P%k`dIM}oDYf7{Ra$G4d6 zSz_|Vu1xIe7`8V2@~hFh)--cFVGB^Lm24KY_p-!4ThzFrfi~gAbuyY6{5)atN|8Kz zx5P+vj$FrThpby}1m9F84c{_nD@cK0)j8%Z;l!D~{sj!N-58frkz}rWu6N6?v5V2( zyyI_@7^9gjgz9{UJRNQblC!pAH#97ek?n-!f0<$IEDZK$Y^pUd&4@WSc4t^CtZtR` zs-vCDLXjwD(vjoFILs=r(Zs4qU84xOHt+8?*u|UXRSa%-2KD!vR>yJ~BN82jetJazv^X*G?SAhRil-QQHWmMTNn0WN zoWOm##Kp?NUDvnZ7`K9OaZmYT=T+vdrPztt9QIdQwZ7&_8oAvpSY zlCN@H|E31?K9KI~!=NM4!(=(OPR_&!aK|kK`Mks*J1t0@(M2Xg%+nHH9n3ZpmCdFp z2ImSA0{EgNx9H{@gdJ+K_sJm*HD6S9gv{~3@;7UYxesw=8t%JH_1T=-iauL9xcS$~ z+qv6`XLpZHd*MO&`c@);=1okBt-gvkG4|O|XhQ2-#P=be~f_$WAMt`9z}KM5=2SH1opZ0A9||-6M}XFs9{wGYan) z1ha%GSlGpD=IU5smxi8@`+dPM$5=O7Db|@ z*rN~naAocFAg?HS9wXAl@J!AU8-!@a1Vv9Vyt#@Q-s3G2Uf1xJU2JWxT*K2yS?7Mr zt68xp7nEB!T5UD-qDP*M7?YnBo2Q9q>tyX0o4K)lB+7B0S);T$Ow4W)xg|+4lEL)d zwxfj6i1r3P1XS#~;V1^D?z!*Cm^bm_%f12ZDL;(MUSQD`p7C)-~Jd!_blFSfjLv;rWH%=DK=$wJ5O?v?HNI z?K>DDTGhmwqnPJ*=E=#((k3To+25qh>x)bkoXv1*(QMkbs-X)(>MLuq$k^AO`iOR; zgUweT?qa$LW+44}*LYFFI|}f$aMsgQIo#zQW~?d}WDo*XzHVddWUE;qWR*K7yKRC| z5Ss8c9QH&WV_3HLjlm@cM1s7HYyzsqEN|j1tLO7_(_^Ba1M;5Bv9?S&8cLHiXGlEu zQgopi(ssDZbPy_HD^N@zedJM7Bs$YLMNkqW=ixAc!$Jc-kuMo-`I6Glcf|zP!@SgI zmb_lBm5mVTBSvnba=M4hG*QV~!#>?_O-{<)bGoQe`xLWsCvLt4WCr>rvy1L#r^H4s z+V>fOCdkHe*%+510k0Iw$l`#3n9?j=#E!fNRXxlo#b7@+2c|aI?Q)K>&3Hc&iV-08 zFX-~EEtBu0Tr3_ZVQF`jO?;wPx3t}HzfGdcnH}at+sUmZqC4?TdWVHA?m1wDm!7aM zWXV0_vTHq*c@F4b8Qk*P-%bB6yDB`@5d53QR<(qQX-1+Ma!sV?+$lRNI3m$7?>ll% zC-1oC4UssFMEg8x3`ExWzMjj|7RUI{ecF<^f67OYyE~Aq74?{k_i`MQma<^ty_@I} z|CJRnSKRWn#^jobgwwr&U2EnVYntL{s#1rn5N^uz9boah!5JqSw;yT7lo}I>o{4N% zS8pC}orivcsc$L-O}&>KdsxL0;ys>qHTjP!+doM3SR~n5bd9%#HbRZ6S&ZoR&>AX{ zAKPNZu1s`EWDR7NWQC=;zQB?-T{qxyq4L>&9ItWll9Z(QP|4lrg-X^S8!8|DE_tZD z_JrWOuDCK+lQHs=3J&sCwm&eOzH#ksk>XRvdafq2-;VYxR-yjt6Vh2#)R8y@{mX+$BwI>0V~y zT)u4!XC(SFj2s&9tlZ^DwdEVq<~Bgi(KieIN1Khs4R4k3$|;}iI?ps&vl`^osDaJk9CNc7;CbxhU}4erft-QIjqCPvN8qS>-Yk(X_S6id;FZ!Emi6#xF_{@t@1yVJ%m4T(Aa$Xd5M}QBl^7}ud2FiISePmqf#WwAQ&1o8iM_yiuaTf_H;T>ZR+?*egum==Og9f!nV&J0nJqe>?QO$9!%Vn-C_fer7>85!`Ab zxGy^$?sg>YsM7MxJrbQy*W};3Sxd^q+#{-6soV=b7wk+!hZX`~M=|T%c^vR`wYW%U zJjVKgIRJ`8FBQnQuq3}b*ygs^yd9S>zT`}{cQM zZ?Tu0y>yZDM+BOBF5jP#!(>_67;mQOFYBloexhkcXf|`0W53rPJx7oU?-q+2m=+6M z*zD=${q*Hpn82BQxaZgZQB~;1hRIhI*uwICIl3mV3Kd=Iubrl?H68K;E!J}Vq)H;H zkI{Z%t9+q_?_G+yYu*wjjg-U;k8@fEopD+$cifs9TS^lxVVuo_FWFEeez)PsSWOn{ zqO9oO9^pj(9R5KgduWNuQ#YDDy8mt`=1X;4wNzrW0Wyv&HqF>knE9oW%S^TQwkpij zT^`)THnw{18B)xN&f*ZymWB8*jk#G*XRb10ZQ72OlRx*^k4Ugl`9nBTm^aT~$2Blp z*|u}uBImI9PHtwe>u22P#T37rVdB@s{QK5i9lntBeW9pJ#v;1wcPBa@_Qj^p<^q4WIeqVkTL_X|jFEF4C85_K@C7wr*G{_R|s4lDoIq?)6x~#N{31 zdc`F^?xZ^Fj~I98T-TL`*l*#<@+41HPJ>lE91MxWrg`N zdDN`-Ev^8*pqJ_Ug5EnalxMy8Jd>i4m}Ax7lw;RhMdiT!medK0&MA79%T)y3~iEP=f ztIbQz^1~ky{Sr$A3P(XxpqhaH45~pPpG#hwjl|Rfe$>IfEULzu zfkDmUd52-LcHPLe{Fq@-a>tZ=c}>!_F5h<$jd$}_jkWO0FJfW)NTI=#XAfrS-B2*o z$Nfh1svWTu^e+o_O*2K=Z3v6)sZu>6KK@GdfqRt9z9FlmM4Ix5xQ8LgBVzkodpxOp zz#EU-f%r$ncAfQWfy}5)tgbZO!@74tk$iIp#9dJzdhn7&en4S=g&am3{3wO_3PT2J zL0iJo9jgnzrGd9-;fvYA+W|?(*l|v>XQV1R6R#!oSIQVD3~J^mQQya`lIrYwb+-4; z+b=-GrBFo9qHIid!@P0v7n_0m3odm{6bBPz0pI zB0@^wK)@!K`5i&an@4Qw+dFu#5D2p z*rh;#uE_en(M@K}Z*y|(_hpD_Zf2{z(LYsQcD3(DblWJdlRd#keL?*n`tBlj zz!tpW#I9&N@BcK(&V*wao~y`%5aYmGJ`r!rlo-LBb8N>71mIHREmf1c* zXy&&v?14x#gS40dV|yjpRDo{A==@C)GGa_QmG5qvrj4l<^IYbQ=mRcVLQHzqeVDD9 z-t3a>Z-#ez))M>KlG&}KYYCpw@O>5L+dIRKU69wvg|FVu+QTL}5M1Gk%j8r^m1vxavHt-m&W|jpBczJsCZmPbENGr?g|avtwPKO*!wYr{3WIy?Ez2*2V1S8?x7jlS~J5%y65`j|LbZOdLl z1@caDBGLafj~l(sYk!g8zJ)K3P)_8B#zn2yeqnqO_1=S$B4d=aOI|3{a4|s>8E*t9DfF=KdUs&8iYG3DfIlFpcUi4og~n^J`s_} zAF&5jr<%FMJtQ%f4nNyS0WuHJ@`Z(EhndC>fsb`}ONQlWWkHQn0wem{pSyYGMcOC= z)aaw9-_6vVsBE$AfyFpuG`Y1*=MFw9i7or)?UnD?N2@3D9VKh)Db2Qz37R>NGg??i z?-Z(L+rQHuXpduKPrm&A^fD zfHchF?h?IcZR*=~Y<@(abD3VkoXWV7$w24NDZ!XDq%cKfw-d&SdqCNqFneh$&R9?OmA8_~IP zRE1l47-%3b_{lcu=|g}zF{Q(_YnS(9+rrRjr22`v60N%s&OMp+4M&8YM*yz`+w^s>>qcr zG@Z{s_|QI&#NwCT9lPy}vnyF0AgghUd)O}finybvpQ3lHZW~4Jl7PeAf#)HpH2>cJU;xlv7No&4b?rH z78?C_&4=V~_9d6fSNY}p$o~K5jg0p!?iMIAg;Uz!eZI56cNX~00^eES|E>knXPaOf$9atf$HML)q&%jdQg%7AD+3ip)z!t7 zWn-KGA7^}dS@E&XoT93dxrJ5Ll`xGNQ#hq?Ze?*%b+HcAm0Df~Z_V85Kv_*`X`rmU zI(hl~u)oBBoqs8r3DDT5)Od!s4>(V^yyo6f=*~C4s7%ii+~e>cGO9((00m z(j|kfJpxxRC@w2Tl9{R!WrWzQs{%!p#SB+cjnR-qG%PHysx}>}iWU}QugfcoQAF%m z3{C9p>u*hzs7GaG@%+MzhnXm-sgMa31^N#kx_J1o0fQG7;rzwP`}y@MpYM)6d}x4Z zDlM+68saP}o?BgBX(DG{@%$p@TUb;f9yJ!3TT~_?Vq+>$RXuOa7~3IGT2y(tu|rW= zU}4eX!m5&Miu(^xGdfB7%`3jDrZ`o%w4*Z4n8(inOyWMMWo2jQ8m<@I!mrK&iyAvS zoA?EU!M6hW0f@RgIy*P<`0F*`PT+^YCip%BwgL~nlSgjwPXY#j4+HaoPXlKI-v-tK zqri2*L)gi+0*3${i=?gW+s z+kq>AeYoq{2>d><8CU>p2hIWJ_HvvJz!AU~fzyEtxG%jHxF5J4xN>c0=MLa*;9lUg zd+C>hU4VJO9l+_pcYxKv{lHbgVVvb`0+s@I0k;ABJ zUk4Dfju~c+y|@#_U6Z&)&WNVUj$AE?gCZ=kK`6*74UT6CSVY_6F3dH z4_FNB&F@{^1{?u=2sj;B&8^a6;8x%|U@Nc*IP5pv=2*=6g6{O9;3BVTMFrMNCjwHT; z`M?n8IrD(6z?Hymyxq77I03j5coDDzc@@Au^uGZ(3b+9{6Ziyh4e(2#1OH&&3)~0% zKCt&u^aG9nUJINKd=yv>`~ujguj9PSql($U^4~H(Ft8cB1IGZ{fe$~?+1dAK$NAlp z_!&59D}2Brz9;<9AjkO)a0hTZa1CXff$QuM~2F?bSBIjD* zX5boN3vfNK19<*+>~swA4IB?V=8xD3_t1D&QL6{lLw@ zw}36co-d#`@JV1_7Q*L&X9D*DX92%{3B7@rH8U=78E`xB31AfHyo}!LYz_qW2i^>v z415q+3e0|mxB^}T+zh+}*aBP+>;S$9>~lPFUPW)ws?on}DNVr=9?(0G$(wD_{WF0?Y^Y zc!RhC&IZ;3R|D4pp9VGo(_82d%mX?nk-xwI@Bv^xuoE~NnD=M;1LX%3*8vv;n}9a~ zTY--Nos)?>U;xpL^0dO908E_eJ4RAg1pTKRv@$cYw z;03_!Q~19l0{a7h2Mhrtzy-il-X&gvmjE{a>ww#VHv^-zn1|A0UriV2L2UT3Ow~M^atJyYzKZ0>@%1j z&3hj^0q5_=PQYcr-6I_5bztUcj#?c^zN+^3zLYk{kQPXg})?gAe4 z59~FZ_ynE+TnQWx{0KM?_%GlxVE=u@8E_168*l+|H}G0uCjQw5JOSAIGx`JP0p|fX z0+#`EKBqtM65uvq3$Q=_41K};fb!{Wfs=O4R3~k5ZrV{jyJyQ!APSz+?zArJ?8L+b zdG}lalnDn>&Zrx)O*$97awqiab6(DYS7+BcXCHaSDZ@{og4w>afXA)u>^x8qV|(S^ zls@jDZW9DK}ef-d8D^dH3NYe63XeT<)86Qe%~{&?tf{q*$941>tr#ov7BMsaui zNwNO>p@Wj*D*exdo)4YWkM*Ay>pu(nUD$7jpPnA^^po$^oI-z= z)L8$EV*S@bKj|CjPeK>__VV|i80)_adM@-c{PbX5##OM0efC2i1U=xVUlQxz7ykFL(c0dU)(_e0M~eme6^9~+Y)zluKrp3#1u>KHvcgY^x1 zGGE9T?flJx&NAa<_VLYSPE5vRmBCUNo5$=Jy%f5{;~{?flo)*_^qDE>0s6?>|K~xU zz;)&tG;!^z6BS!FBcl`^meUx$$c`cYkatKcq2I-I=1iXqvDYmzzE=2l!*{#zot3~B zj`3w<*Mf%5&Rc}Qsdbyu2Iu*xcJOs}fHz$vG zk+B2%0O(ivWt_V*qb}1H1+h;%JQeVyis@Wpbq;j4pD{gu7}FsS`fTW?e7g3ph|vq6 zFM^&b&MKfcLQj>mjnJ=yE;ZJ(6Lz?QAw>U;&~JmzZ9$AaBQ}0B^p(()#j%+`^cCMg z&+SG&LXY!9x{PjXdLHzh&{?))y5t=`bE&$cErYC5F5W4`n+$Tw?nUlp3466t1+{of8Q^ENlbno^y{E=TN4|9W{h3{ z{YT#*zXE#6H_#iQ{{VWb8nF@jMCd8!4_)k&EItCL+z!0}`gXtml4nobIh+7qekEle zJm+(rIraG1JZ&zWBb?&PGl_{K8&l`XEa-ipU+5nz-7X-~|61thK~Lq2wa`aFPZdi~ zLSFzq)%v^(`gG{$#*J^(cLLzH5ewHsmsrm%J1#a)U%Uqn;C>jMDRDAF##l0keCVG+ zPo?8*=qKKq+#k}v7J2~s0Ka_S9%3Ez0nn%V>FIXSkp4~3FM)np9NiWyp|?W6>l?;* zdN|JQ(Amz$=3g3%=K%Ee(B+FtUOmc4OLJo&ANo&j>+C$w-#g;5D>tr72<135l@(^R)22WgVERWH5K))Y)s(9E7{Z{Cy zY}J#FFF{WhFJj9<&_9PhDQ>QILo4*j(2rf6I-X0R=Ri-j_N;{NKu?ytBL5-iUow8G z+OPxqUg%8IXXluG_CkLhI!9+Q`h}Jr0JW1?*#TYFw#<5V#Yxt;yq=sF!_yxgk8aDe zsR;$pKY%{jPftJB3?g%=fPM&bOjW-cq4$HH%10ZaUj{u@&1i-`8G5QceY?`-{>Ib) zf|!kR4Nm*8=EQeS>}#&}Ty*>F-Z2NXm(Q8lf+OUg4*w zU+Im%5&Cn`B~(29efLz&&>w}KDxce-Z-Y*T#rpg9+H(H>2k7Vd>6*`?Umo;!=qcw9 zJ+d@;y$aC30{TCpALf@|VC^p`8DkYZ7u}sY4>m!UX9lVAXeacs&`3_DLevO@j(5FK$pntMGqSVAQ@xgrPd%4a$nI3MQ z+4Z$mB#E50$ocdxTN6DVVnw!FLVpr^k2^X$f5Ej!PruhF5&*Re`by~4e!8snb~|V8 z&$gq>E_m*QC-VVzjq$qFi!jky;%4%lot-D9!Pns9lRAEst>dCoL9TsXl*%?0(63mN z`kuTI`cUSa%C{S#9|t{Ed^bZM0XXvRcIZY?ml2 za^(L@vK=|e?ggZNZ$r-2%vH{NGT%HRCTC(p#>&jPtc)9D>vMmSe7Jgd~{XwoXZ}*KQ_Fl&z z-~;?EgYP8lIbQe{`}nT6JTg`*V@-f(CD)$L=|46MLYITSN1+Gg+MSc00SPY37($=I zb!H#m80oP+@OWhGf`>bWm<)RiXX0=k^mn0S!Wi9m4z~s>pGKXsk~Xc9LS@ELzL`S{eI!XwX78{xT!>o_^L#(cgLp6rKG=ixr+ z>CltuEA#2i(DJPHB>xyiG5I5)?}JWg#B`V(qfdwa0rb=Sbml6%7?EEM{a?_N`8xo8 z74)9y_eetj^k2rt*bL7acv96^G4oB(Pw~spvn26J6EV>Uy@%AAOE8GfCmD`Z8JlBK z_$nXfxd?sY_|k0v8UOPv`C)ic*=rv3P0-`);X5;02K{;H$<`c^zaDx!^kn`DK;H)a zE$DSz`{$AFJGY3!Gv<-xF)a3w=kg<=U&?jn)lAxFk92!XXKGFde5LT2dT@!4&sPuR z8TuXY4iPUub0St4TN`_5VS zL4Oo_4?o@BvYL9;n`L4x^knN;fIcIj%ly8{-ZSC(9G>C+F?{#3i=iK|F?kNi9M?cU z68boQ|LbCN+zkEu(2w)eFOAV#pyxwRwoebxrvv(V(D(TJOFeooCZjI~IQZA8?R+Nm z6QHw=h}rqPSpQkj4~3rUUhZ1x7eXhBV*P#hVr!uXp%?q<>GnWfZ1g1bpFmHQce|iB zLQfSZ`=S2=`bBZ_?G3TW?@PgNfu1UF&xHOF^kg=c{FBtf9U<8r?UT((8oegrT;GIdC&*@_4l2X?}vUC^i=-odkpVL zKqpLM`RRK;c_#FepkL~zr`yBu0JvGu=R%+Br`vm6^OP6!JGJoq0-jVcxDNVnpr?xA zCg^R@Q>~q?(0gr4Jx7OwqW$zwHOBz-4(O?JFdzC}=tcfHrrQIR0Jz!E0Q$So**?bf^PT(29&~zueHCL|&UI!6p7ifQb#Ehl*TVNYd|QQY z&jIm#n`3j@#h4Y3cXmDupC>E*0mC3V?}z?1bV@{w?t9kT_jsNq{x)@OI1~D8=w<%? z>2`q-`Lm!u44rL8Oup|~?X}Q1Ku?v|YyVCEC$)dF+9h^ckI&a5e=^sZuW>`;x2Js! zX7;<8FmH!1)jE6v^jDx)_~+p}lO7NKxXsC*fd%L@5BgN-adwg#=sP!G0nb`^lAYN? zaw_oEdgzff=JLJxxnw*gr#<#wy&2|lPw>7PeZ2Xm+nW#ZNjvoWpvSGL=pv7igr0jM zbpm>_JzoHN9`skBzreL8U*_^`EbgYmbM5a_-yc^)UkIJD9Fw8%9R)zGf?f)JiJvZG z_?~rbhG#20$$T&KXo3DT^a*|$y6A{Kn~0s=&~M>7^Y7haddN7-?OcQ}3g2Yj7p@h) zR}=UaS-t?Y5J9{iK8dwByZGX)6rLUMq&f#$3H?dvz5FsJ#_akK^ar663b8SK_dGkG zKLmY_pPp_R#3p;8e+>N;KV8oRgx-_j>wunWof-sv_czcdLvMyY#xLLZzFH~t522^p z%dCVRcq(<=JOuq<=*52ddOs8Zw*&e`&{OR-gr^;zrT>PfHw*cCc;t6}{l3gN%$|#g ztwzD~vuBdmd!f&S{xbArz6?NL4E-7CS8(l(;ak&%XDvKgO{sZg9C?3tGCZl)?N;dd z(2L;p#?k$m^mizFH$YFOr_ck?%b}-QxAUQ23q94kJsW!2H}tR7{;Bj|2fc#+A<@;X z-@fOOP0-gsPqps1Lf`%kbcbZ9Oav0q7@eNxkmpL!S#hRsY%0Z-HJJr@uX{ z5&PCcU&A>`s(r&c=+8q>wQm@YjBW62U<{KN6ME&|l0LClpPMs+y#fuH!Cw7WW{vNa zcT=}euTgc~&+V08)@#(*UU_4C^*^Uq;GAB4&gqqVPOof7YEsXE z0>pi3S-fiTURo9p$;0WJ(;9m?8#1TvKft*s>-QPa1DxmN|Ed79`*%QP))MFDG>beS zG@!~^p$(S<_Ir*^JNyR|D6(k}rahC9_F_hlmJH_u`Ja}s%Gr-kWRFo}mFK2Q(5GcD_nY0hub2AO7VP1f(yojcO9UQKsiOlRGJ zrDtPW7H`Zwl=gUrY4@0&#s47p+RqO#t)r%9J<;7M`-;IH$jEB$?%bZ0^3l$W)*`1qVMaYqW~XyO)hY75cjo)goK`c>LEcKGR8J2KL~5*?;W}W3s)$XF?QC#O|o$Ji9xE@z#-JB-QFj|-%C-VR17)x8m!k){8_EuWf-_q08 zXJkE);r!M=jPx+Q#%5jNTrX1YIV`Q`Nm=94=44&&)PPXS3*UF2?=0~DmIc>uJIm#=iDD!llhDAB4&2RPIZw>A7d^DSQ|V^U29BeB z^D*m%UJFpMY=A6Mwl?x{$203M?d}HaI6N*fp9QL@i(jV`arNG=hNNnmk30Uq^c7l= zhV^T0H>sgIwXM@}+O^$R>HpNWJ8u>L|9P-R{hO%hNR68b3NKPPU*RH!Hz~YB;r$99 zSNNR5*A;%C@ND83T&I`}F6x)>9P89N z4}6f87UTyWUJW{#|9d!J2Maj4pRW$hAgnD|G;uGuaH1KK8 zQBLkZxG>ii$~jn?a~R((vu*d^o4Am1-FoigZ{s43mo41-=;D9PMY4JAF#Jb32PcgC z7I=~WC-!0TnQDP^AO;n@yMDO!uLyiH`B$gFyW<{`V%!IGU2?~jpQ)B{-Sx^H_qYE> z{-G)4@A$EukSqTWD&JiPUHPf}-T{A_bBME}MGfNv$?VY0ECdHTq5FJ{Ty7vB(jB5P zA&8HFKaJHPvCbW5mgocH4F!>{L0*w}5tNh~?Kl2KUaM$Td#iw6w@xzt>Ud8uZV-W?4e_rvewH8sN z_zqWookd)#_%YNR(P#4yEW%x{FH!ul=UcqF59d;T?o;^RzQ*DQSl~1%zV{M~FwefY zj4HlW=jF=(4E!O;={w!>SF4=wQMeA#Yd^>XFXJv!eWdQlXO-d~Z?NqbEO53fKBR)( zasQ?Gc5~Ph8|!!$bdleDffZoR0J%Iv@l(fH`~sDKvEm0Vvk1>VivLpW8C3qYiht1T zrtCT(q$b5Dj@zR6Utenlxb~F)&9UfNyEGpEeZ{X-`-DL6vxbJ7&c==x=p;-^4z%Z5bg~4mX2M(ctxH5fc z=S1+L=g12z*46WeDfn+!{vX_B`6sKeFBQM;42w|UEFyG7{yz2BcIAIU@d3>vSO2dR zKU(eJ>NDVAD`!HL6);=nOa(7~NmGQpPb{Asm4AMzZ3irH?os^ckVUw4Y?I>0EVOvn zFRv?pnD(8L0Z#my0`YZl;j4bnQNQlp~6~9>Pxw{`IQ~ZZ2$F=8u;ALJlBdlQg zuC{zO7`(mq|NHk8_(Ko1`XsKu0mbiGZKb$%X0qZF_X7(RAJV)o*TFX_zEKgbJ$Hf^ z{rk_bj3=`Hlh2pR|Md#ncKMGbu$e-a&m{0-&zsbbQ zv1I2+{3CK67;X_e6u(pPud6*TSNw-6=e%1i!j*s2_w2aW>4e;Q%?2;>PyV6hm+v;n zr$+hD)w~#L(at)>?`^aQcfQSvPuyR9rug%IWcl5B_2=M6>@Y|3@o1GFR{Suvr<^NO*^9UuT^|j+})_Um1+l7j+ zUu_wuD*yG0pN=2ookz{w$mwA z{LQyoIj890s}w&-@pBZvRq-QqT-;$kZz?|h2ey5-;%f-JgW31iYMx%J_y+Kz=O&HM zC5nGc@o#D(y7PKR@jI@zjIO^94_G-9G@uSvIpY+ctMTCKxkB-4bzkA;^@EDP_zWw+ z<$po(AM1MR#`E97C-YY}37ZW6Bk(fcYjs?@o6j#5zgP8tQ1O3O{3#b&gqwF?E57u0 zi#P8ca4GMdiTu82S-h*iybmP!#QTfuz)L*ee39jM>-h%dKk_FQUtoc=&G2i(2VQgK zkF`j`z0N;zXQ#ysq#KTmJ z*sJ)V;Kgp^)xU21U$6MYeEEgq_tsber>LBrM!q(Dpe+Ty*U5I=0>{V zZncc0iTU)UaEU#4X+3fE$yfZyahA{3r&RHYdA&*Tf4b4~yY=BM#c$MksX3f193kUw zQa`%+b%EkfJ>SZ4^;xR;AsYWBmh9ZG__M}X1k0cK{890V`95f1a{C0qi#{i+UtIl* z6hHDpD|e{MU#0ld?z9M3|6eQqdG$+?@_(%O&062wd3|q?9e0%0Ny5W?E(D*}A;^!^0ZFgN8GT7d~IG-w`f-&G_+{F8=ixod2 zY#Apj{}RP7yV)Y#`QDvo^ZM+W79UmqweTmK?>j1|Nf&C@&W8-K`i#B73YesFhA4ik z#+ADtlV9u>{j(QZM%Rxk74Otryu7C>pC=WcxZb^|_%-S;SLb6Xm?Hm*pVpbxKBDlyqj}v+@$x%~g5ObV5!|ktPZYd6mZA(eFwgRjKigt&QR4B6pL>Bt zxZ_@=_zI0%SLR~HKdlaQ_uCIDe%2Z*r$FVmf#yuIT?osb$Pn{y`XA z@DE;X5pMmNqWF-;p{q}Y;&Zf~%vCw>D86NaMI5O3J&IqdcAl#EBZk>=H);XaZHiN< z_{4g?Lh*^`(hn*A>g85&p~_FkP%^K?bv8%w`!o>lQU22upLkz9U-3Kdu#82@zgqE$ z=fJ;L{Fzr-M)^LheEzEV+ce+ZxSBvB7{6#9QI5=Kmf|nC&bHn9utxET=NnHe{s|3) z3YF8L_)OKu9d{rLw2Yg7zGZalOi=NO&kN>)m*)$K=hE`Km$DzYT??ChpI<)rs+|AT zg@tlqK7UmF#Tr*V6h8zz>{Vh55Xx_>MKU?dH)?Hnb8a z6SO{K7W0{*_}*I24_5pg;3XcMA6vx3ihtJNwc!JMR8Hb^x*qHsWZWl%mRYCmoDV+P zd@oo27OnH{dVRa%d#K+p(y_NHzWG**plLq46`y#X+>N{yeVXpDe7%+bbnwaax!T}+ zIp^zux(qn?sGP)o#cPVcC*KOjg68w7;$N?}?V}Vwl>L_Ivsmi`W;CC2@RCP~&jEj= z{C`w^T>IRo`1`ADf414?^BcwY(fD!4Z2_NbzWbFw@wx4(tj7`$3ofy8k5u_%z>EHq zHL=|Kc7@_!*Y(AzjRJ+U_{#n;u=braDRrP=wAmDL+kHvn&hWeI1|Zjcj^PuYkI?^{u+cP* z8@Ig1@RxqYjPoFm|2c-=&I~H!zr^q}*Gxmf`TsEdw%;^xng7}I=DM$Q@b>cze-8cV zbHyAg*Uy{wfBVY@Ao%|@!(IRPD-3_*qo%#!^Y!3=TJIOxt`@$y!0;oMpH+&BbFq`3 z0^B#BXSluVH+_rYu0Qy0C?>k@AF^DP@h1%bz@z56EaobI$MA2neJJ>Rh2ejOBYo~P zhsrylUuk@jPxSe5bEt$2|7o_zev#pyW%$d72JjyY|9ght#O-fo_&YE$8vl;-1|WLs zeulgD+Y=0T>q)-M@UPut#-ZmI(q|plqw$+8-+s-2D<1~jhyUN@_8-E0=_C95rwn)f zoquHbAAiuazu6orKX$jd?nUNbm}mM!`q+2fp9B0Xx3Lco==N`}Jho$?zr{aZ=keWq z@h3{gf4T(zmw?|^d0XY77tO%8@c946<3IEp1|ah1t+2BRpD+EAfeW8r1f1mXm2CqT zJ7>u4pL*251)rZ}_;uiqJ_7%D9_KNZx8HAmuKYK*clGakAvbA0qYs&eF}L4lxEs&> z2*X`{_Z5b_{?s=Z{tWYr%<~NB%(ssZ0#5V!-(xe8pXB*`km0U9@Fc^Z=lP3#ewN`6 zL7&j)C(NO869h7i@74=d8UDUcn1k41=7(V<}(@^m6M+|r4e&1vG`+wH7=R@UI z=v}(*5!0v0w@tu_KHd20KHz70Zua4j$NB0<4fIj|@skX9?U|<;?&fo!Ww@JHee0J0 zx>dkw{vYM}Cw$%e8UAG!0AL6G`7p!3!}8~y4F7G0-_CUSAjAKf;jSP3b%v8YOCRB* z?*LBn;n5cjT;#*M!4H}anLe3~D@}&G^gm*_8}I!r!@t-!;|st14Z{QAk3KU0H$d;w zbzi<<;O{Vp$~xe*zrXMi19*nvLvH_E#{h0;_{Vg6KCur`E4>qM3`?qUMJb%9akN*V zx1j+L567eNWOo-|+sQE5OGkK{of>yl+`+5tM(EJ)tG!OY6?Ie_FC`nPXmV7E``tk& z87FNNSbJNjU5u}y;V?SJ3-rdr(Ti_npV`^oA+J3 zu!$~{mZ~dtH3$ZHNgrOVM;GaKx3`+(b4tZWM?nzO>=*UbnjTJ16)zG@hQL}UZ4IO0v6;Sm{aQ_4SQlf~2MHFT--(C04u<_0 zZ-Yxl{+?U4<*Dl`?sKUYUh4wOcWqy|H&o%)x>7hpRlEu>Gw|~Ic15kff9t}%^-K7z zum|lT0O%b8)jak4?z*cP?x>v$7dJzUdKDN8YU+Od#ySOzCG`||Ny9LQ(sp7>+Z)XV z?y+KCSXXb3S6aYjGOllS7i%G5v>B){tOa;!qP+Sp+t(z-qUeJ2Zc(s6!=63eNa!>XtbJ(bF6c{mR-P)61O-I3`etiEUl^#^3DnMl!W5b{J&QG^_IeXdp^LrbP=@Lcf%4US+{Oki6GJb6 z*V0Z$fgkFPw3}kd-@RGCczAh6n3|`*u#)eHWD>&?1yxQy0OPv~0s^0SKKqVlNrf3r(4;Kp!piA~pc00`~^> zdV{AqCExyc2P_EZ&n<930EVSWV?c_;prPhDL!%lmpY$$>%EASq~dt;udCK(W#qG?||H zD#QVHNbN=)@F7VFBV>wlf5uLe(i5G@>XjLATK&4D44i453Y3se&2&TqP-4L5*h012 zIcJ{5MS1V;^m~Y*HhOpy?zL;z3^nE|gLo;|85Y|EAq9eu44La~Vx6}{a#T;S2HZ{W zG-)(y4}qh%Rkzn9!djz5bOp4BEFh+}yp}XMaviJ(Yv>D&xkr|oXf>LK+301G`wMt2 zwC3GhUBKQ}_4{C`wt=Y0D1n7_b!(%Xa;8kpa2d8r)FGK9qIGVWRI^DJrq>OSElqQV zof#}ch1iC#m;?)g-e?SweE^d{?_+>DkN1cDL+A>KHnM_T#wU9AT4scJy4ublw|PVw z1&hN;Z=AxvNQT4y5P}cl)|M#MT0l!Vh2>a88d(AvN0)6hIO-geK%EpgbT|1G!OAev z23}@D)k#7uX`?~YL%Akwg+R)^@KVe>oz1#E_RX5MA4unfnT{9@&0*O zI2SI~RZv|t*eJ^GMZ92|F$$64Smt6?VI7&mKO9B_(y&6E>L}DX@lrWItds=it5J<=ybJv{a6IAULf7c=_y;j3cJmaWF8L0uQgThU>#6B;qalh~e_E4Ye?(;6M5@^V-ZFP9cQ>`D#GZKdtWVVd zH!l5=M+lb)dOI2;l+g|w2qRoQ$1i{1&O4M%OxEEHoE~Yr8}#FMo@gqW#a>jS;^1KE zsn}%AaWC=GA2tpc@LDL?IT%yMEJd4)uQi?c=Z zcZdDnSPy1|kx|WN4n~tYYBZw-Pq-&HnSy1rO_@#X-OrU#YtkLWKEX&4g-o>Fs60ea z(DW(V`sc{pr+EXNMRm6{f?6=B%!Op&1XZATVao_Hg^iX7rDbJ&;!F&-wp-do6%$Rh zM}4)A*h

~oN3BPKpG6ejlWEQ>3rF+WTDIBX3XG##m=zZ;V10v{D3HmMb{0lBye zEU1C(j83EI#`Xq{QLBMURDV~E_WQ#z{BJc#hH1YIdZC|b7_Y?fO;0-o(km0EUdbzjNsAqjTjp{FSaC*+l(&*5!Qz)WJzB}m9nLnOq)3uraLQdqTasFWvoLf{%x?v@*~@Bs848n+w1Bzr@h z{vKi^+IN|fxY~%{9VYN?N;H|ZX^!z(OCABk#vI17+F=v14ZR5h!vkbe5WTCDXVc0Y zH5;imv5_I-!?D-mM08(5 zwLY@c;Wn|Lbi7S8b=1^{9nYD*AWA>1J|%` zkO}P~<*jPupDw`ZT~LsJ45h%!mC;ZuND_oPh5#7|a0o&rrIdu>3K)}2o~`DRszZiS zk7fPM(5{)%~sH5AR+SCX(A*@Jb43{9EgwhRngs;pM^p8kRZ_@ilMG$7mFG`4-H36PRW(i zve>>f?Ug+GIz)zjG=?WE@hhz{VN@KYO+|7c!M;+38Y)Ohj|VGu5!}{xxF*8R3EVgHM1C5s~HDggrr#qgDPUZ(gv$^@Zgg(F_P_&AydZx)!w0-DW1lgO28*6~?FnkR!}1zn1)Ttn+pA5h7Pay2O}y+Zbp|DSvsO{#W=Z?tu=h<%F2~! zG)nh+;WlImH<=f?C>kPiE3MF&Qr6m3@QV$1dW#fO)sn(mLadVyEevB7bR%tWQepbaxyo)-_i0ZViClu8& zRpzEZ5H)!enJTcrhw=(iFB4z%Lb zTd~QSiS4-+qg9WCoChdrJEsRvv=kGi8=A;ZBeRI^l)1XNM&g`rtnf#IO^$+18h?F~ zr!)Y(0V137gea+8ZU^~2C+1wAS0@1$%O#fzY~HjYQr$hy6kFDe{39aj%wcm}GH`q| zuWm%METiC+Wzb1$SwKvpVOf4LOa2-$oK=!!I;5oX%O`eDEW^vij>%22EtQp>XlZ8T zh0bWo%^o6IwCBii(sKFXVwhq(z>-Mca)ZiJvSd)9NRVxlq7lG?v7EeS+yHX|dBuDy zg;S(8odz+rt2*OjZXd7<)29$%rFUPQwt#5%#AL__D5<`aknL$~P71v1h>kWSW&|iv z$))coufR;%_V&gsw}8ok@+< zyqC9WKXP43vX?2g%#Q*l*n}_JF)?v%1?gDRxGK=*R#;<>H&n~EJc7LUl(Kn(u4|@3 zk6iH9DN`=I98Ath89-e@xz1ZkQ4rFCDn0mm;l?Vb;?rdigiLX9ifF3VXq2f!<3LXb zBTyy`fj@dUk413U0Ah`6K}u~(q*$5-F{;QBj^G z`ev5$-js^X#Vf+ytjyg_DZd}ic*JyraIE6dMCa7!Q?MjYOuaM^-XBJL*)6g@Wj2Qm z4Zqf7L(fb!)9p(EoJD9vzVk|q)E<>n>71Ate%LoFhBHICl*DitOHX#%qEp`NZsjM!?-0fK+F5NX6 z>4_o}LvJ&P8CuC_#}v(di$Qg`rRYKjLGlQdM49R*6ntkU#k^FmOTRKlP2VjGqt#dn z-g{!nrj~t{7`CoM)HP?i+zbN{%c0@iv!N=^S6}@hWk%$|%sT~2FT24rOC>o*DQ@o3 zZr*9-F!;bO;ek7NfJ~vNJAq3I`%Gh06Hp@<7rtT2y&_ z25o2-A0SY)Vtoz;nR%JMC|aqoK!8xGI-UwY{&A2M3VP$V(I=7_h=|dWoG>sFYFHB5^5c8Nl)FRzsN?wU=Ep4OD&x|bG zAjNvM6N~lqC2WQ6VkKjwqEE)*A-9e}6dv&BUu9|bkA(h>JeUEffw)EEMOBBJbsu8Q z*lspdtUQZ{#?cj?oZza|cRw-mg)~>e%hHwir;xmoeVi$6&1|5zVGZYDL$RIlynz`H z<|*3*x_?yiE?H6&jiEZIHk+z!x%}ApkDQm~dk<|h-H^AAF=L?gRo%ZVHZ{>siBbSj z73~5DRxAZK!AjACOTO51gu)9ofR09UdpMg5LxY1o^D0)TI;#wo=+@3oxhs*>FWVBp zfmd#lB%GF;9!Usn>gR3kb@7}rvq2;zn&WN?CMdOp^VF2SjaMQcGs1$F$(o4>9cgnB zn@N(gVoFkMWoiwB9q8wIWsmamhv&D~qq&8+CF!PC{K?=d>6xZMAn5}sZ>YD-Eq{yaXd7~efg$u zR~uBS`iX{k7FrcIb>P0h@v#MJP0~*L&a}-SJoMsDvSO>$d_NlPSE}vf9xh>y{DdFQcd>x>4y7l^p!IV8sio} zeG4C+twsi<9>YBN(2OD9X&kyJhSU>`x@nC5eOwCvRrU4FwGe5oRPivzE}pSyKk@NY z-|0DQU!Fgj0!EjV{+E9kC-}(mIX*W~GlqPp<0JTc#hU-S-fn)C<5T9eBJ-E) z$dMkm`hQmcFL8f4ev|vt{Ap=2e+E~6o#8Uxll&l4Iev`^My@aYW&QLRSQ_^t54g_+ zCr8-_>Q7U1`+o{Bx`d2hS-=T>_$bejH9&JM`A)|t@Mrfw%l+i|m@JGtopFwzcKXZv z$K?3J9(Qp13G`{Fzr4Rvjz1y|`RLN`7r1{m%_q4bA1^aKGc?1Woc}q#(E6qS<=;2I z$gzEsv@}Qe`hNwm-T(8nAbjL__Giqw{4e__=l_5&cK>Jp$^0V6@6wOf$G!dw`0dU3 zlVz^HXd176!yM0=L-xO1Uyd)~mz(h?{jYHUE8Jh&$pCUL$M4|>nxgcV=Z`?|LgIgczC&$~I{_@_NhyKNMBL1>JXYCVw|0(pRv1I-7KBn(-f102DId7lf z`yKe5nlRgDze<1iS>H08eH7ZyI^)Zkf910~&GA+o-h)3`x5%$I0hZ0(G}Zr~x!GLd b3k?g1uX0_1z6D=={r^Ilmdj2D=d|+wkB@)Q diff --git a/simple_string_matching.cpp b/simple_string_matching.cpp index 735ceac..075f99c 100644 --- a/simple_string_matching.cpp +++ b/simple_string_matching.cpp @@ -1,6 +1,6 @@ /* #define NDEBUG */ /* #include "Rabin_fingerprint.hpp" */ -/* #include "general_library.hpp" */ +#include "general_library.hpp" #include "processes.hpp" #include @@ -9,46 +9,42 @@ #include #include -void print_match (size_t index, size_t length, std::string &T) { - std::cout << "Match found at index " << index << " with the text \""; - for (size_t i = 0; i < length; i++) - std::cout << T[index + i]; - std::cout << "\"" << std::endl; -} - int main() { - /* std::ifstream ifs("books/the_complete_works_of_william_shakespeare.txt"); */ - std::ifstream ifs("books/genji_monogatari_english.txt"); - std::string T( (std::istreambuf_iterator(ifs) ), - (std::istreambuf_iterator() ) ); - - std::string P = "word"; + /* std::ifstream T("books/the_complete_works_of_william_shakespeare.txt"); */ + std::ifstream T("books/genji_monogatari_english.txt"); + std::ifstream P("books/pattern.txt"); + char c; + size_t P_length = 0; std::cout << "Searching for pattern:" << std::endl; - std::cout << " " << P << std::endl; - /* std::cout << "in text:" << std::endl; */ - /* std::cout << " " << T << std::endl; */ - std::cout << std::endl; + std::cout << " "; + while(P.get(c)) { + std::cout << c; + P_length++; + + } + std::cout << std::endl << std::endl; + + P.clear(); // clear fail and eof bits + P.seekg(0, std::ios::beg); // back to the start! uint32_t irreducible_polynomial = get_random_irreducible_polynomial_in_Z2(31); - size_t window_size_in_bits = P.length()*8; + size_t window_size_in_bits = P_length*8; // Hash the pattern Rabin_fingerprint_process phiP(irreducible_polynomial, (size_t)window_size_in_bits); - for (char c : P) + while(P.get(c)) { phiP.stream_char(c); + } // Hash the text Rabin_fingerprint_process phiT(irreducible_polynomial, window_size_in_bits); - for (size_t i = 0; i < P.length(); i++) - phiT.stream_char(T[i]); - if (phiT.get_fingerprint() == phiP.get_fingerprint()) - print_match(0, P.length(), T); - - for (size_t i = P.length(); i < T.length(); i++) { - phiT.stream_char(T[i]); + size_t index = 0; + while(T.get(c)) { + phiT.stream_char(c); + index++; if (phiT.get_fingerprint() == phiP.get_fingerprint()) - print_match(i-P.length()+1, P.length(), T); + std::cout << "Match found at index " << index-P_length << " with the text \"" << phiT.get_string_in_window() << "\"" << std::endl; } std::cout << std::endl;