{"id":1421,"date":"2021-08-25T10:34:49","date_gmt":"2021-08-25T10:34:49","guid":{"rendered":"https:\/\/www.coupontoaster.com\/blog\/?page_id=1421"},"modified":"2023-04-28T13:17:40","modified_gmt":"2023-04-28T13:17:40","slug":"introduzione","status":"publish","type":"page","link":"https:\/\/coupontoaster.com\/blog\/introduzione\/","title":{"rendered":"introduzione"},"content":{"rendered":"\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">introduzione<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La corrispondenza delle stringhe \u00e8 un argomento molto importante nel pi\u00f9 ampio dominio dell&#8217;elaborazione del testo.&nbsp;Gli algoritmi di corrispondenza delle stringhe sono componenti di base utilizzati nelle implementazioni di software pratici esistenti nella maggior parte dei sistemi operativi.&nbsp;Inoltre, enfatizzano i metodi di programmazione che fungono da paradigmi in altri campi dell&#8217;informatica (progettazione di sistemi o software).&nbsp;Infine, svolgono anche un ruolo importante nell&#8217;informatica teorica fornendo problemi impegnativi.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sebbene i dati vengano memorizzati in vari modi, il testo rimane la forma principale per lo scambio di informazioni.&nbsp;Ci\u00f2 \u00e8 particolarmente evidente in letteratura o linguistica, dove i dati sono composti da enormi corpus e dizionari.&nbsp;Questo vale anche per l&#8217;informatica, dove una grande quantit\u00e0 di dati \u00e8 archiviata in file lineari.&nbsp;E questo \u00e8 anche il caso, ad esempio, nella biologia molecolare perch\u00e9 le molecole biologiche possono spesso essere approssimate come sequenze di nucleotidi o amminoacidi.&nbsp;Inoltre, la quantit\u00e0 di dati disponibili in questi campi tende a raddoppiare ogni diciotto mesi.&nbsp;Questo \u00e8 il motivo per cui gli algoritmi dovrebbero essere efficienti anche se la velocit\u00e0 e la capacit\u00e0 di archiviazione dei computer aumentano regolarmente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">String-matching consiste nel trovare una, o pi\u00f9 in generale, tutte le occorrenze di una stringa (pi\u00f9 generalmente detta&nbsp;<em>pattern<\/em>&nbsp;) in un&nbsp;<em>testo<\/em>&nbsp;.&nbsp;Tutti gli algoritmi in questo libro restituiscono tutte le occorrenze del modello nel testo.&nbsp;Il modello \u00e8 denotato da&nbsp;<em>x<\/em>&nbsp;=x[0 ..&nbsp;<em>m<\/em>&nbsp;-1];&nbsp;la sua lunghezza \u00e8 pari a&nbsp;<em>m<\/em>&nbsp;.&nbsp;Il testo \u00e8 indicato con&nbsp;<em>y<\/em>&nbsp;=y[0 ..&nbsp;<em>n<\/em>&nbsp;-1];&nbsp;la sua lunghezza \u00e8 pari a&nbsp;<em>n<\/em>&nbsp;.&nbsp;Entrambe le stringhe sono costruite su un insieme finito di caratteri chiamato&nbsp;<em>alfabeto<\/em>&nbsp;denotato da&nbsp;<img decoding=\"async\" alt=\"Sigma\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif\">con dimensione uguale a&nbsp;<img decoding=\"async\" alt=\"sigma\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/psigma.gif\">.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Le applicazioni richiedono due tipi di soluzione a seconda di quale stringa, modello o testo viene fornita per prima.&nbsp;Algoritmi basati sull&#8217;uso di automi o propriet\u00e0 combinatorie di stringhe sono comunemente implementati per preelaborare il pattern e risolvere il primo tipo di problema.&nbsp;La nozione di indici realizzati da alberi o automi viene utilizzata nel secondo tipo di soluzioni.&nbsp;Questo libro indagher\u00e0 solo gli algoritmi del primo tipo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Gli algoritmi di corrispondenza delle stringhe del presente libro funzionano come segue.&nbsp;Scansionano il testo con l&#8217;aiuto di una&nbsp;<em>finestra la<\/em>&nbsp;cui dimensione \u00e8 generalmente pari a&nbsp;<em>m<\/em>&nbsp;.&nbsp;Prima allineano le estremit\u00e0 sinistre della finestra e il testo, quindi confrontano i caratteri della finestra con i caratteri del modello &#8211; questo lavoro specifico \u00e8 chiamato&nbsp;<em>tentativo<\/em>&nbsp;&#8211; e dopo un&#8217;intera corrispondenza del modello o dopo una mancata corrispondenza&nbsp;<em>spostano<\/em>&nbsp;il finestra a destra.&nbsp;Ripetono di nuovo la stessa procedura finch\u00e9 l&#8217;estremit\u00e0 destra della finestra non supera l&#8217;estremit\u00e0 destra del testo.&nbsp;Questo meccanismo \u00e8 solitamente chiamato&nbsp;<em>meccanismo della finestra scorrevole<\/em>&nbsp;.&nbsp;Associamo ogni tentativo alla posizione&nbsp;<em>j<\/em>&nbsp;nel testo quando la finestra \u00e8 posizionata su<em>y<\/em>&nbsp;[&nbsp;<em>j<\/em>&nbsp;..&nbsp;<em>j + m-1<\/em>&nbsp;].<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;&nbsp;algoritmo&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node3.html#SECTION0030\">Brute Force<\/a>&nbsp;individua tutte le occorrenze di&nbsp;<em>x<\/em>&nbsp;in&nbsp;<em>y<\/em>&nbsp;nel tempo O(&nbsp;<em>mn<\/em>&nbsp;).&nbsp;I numerosi miglioramenti del metodo della forza bruta possono essere classificati in base all&#8217;ordine in cui hanno eseguito i confronti tra caratteri del modello e caratteri di testo e ad ogni tentativo.&nbsp;Si presentano quattro categorie: il modo pi\u00f9 naturale per eseguire i confronti \u00e8 da sinistra a destra, che \u00e8 la direzione di lettura;&nbsp;eseguire i confronti da destra a sinistra generalmente porta ai migliori algoritmi in pratica;&nbsp;i migliori limiti teorici si raggiungono quando i confronti sono fatti in un ordine specifico;&nbsp;infine esistono degli algoritmi per i quali l&#8217;ordine in cui vengono effettuati i confronti non \u00e8 rilevante (tale \u00e8 l&#8217;algoritmo della forza bruta).<a>Da sinistra a destra<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;hashing fornisce un metodo semplice che evita il numero quadratico dei confronti di caratteri nella maggior parte delle situazioni pratiche e che funziona in tempo lineare sotto ipotesi probabilistiche ragionevoli.&nbsp;\u00c8 stato introdotto da Harrison e successivamente analizzato completamente da&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node5.html#SECTION0050\">Karp e Rabin<\/a>&nbsp;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Supponendo che la lunghezza del modello non sia pi\u00f9 lunga della dimensione della parola di memoria della macchina, l&#8217;&nbsp;algoritmo&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node6.html#SECTION0060\">Shift Or<\/a>&nbsp;\u00e8 un algoritmo efficiente per risolvere il problema esatto di corrispondenza delle stringhe e si adatta facilmente a un&#8217;ampia gamma di problemi di corrispondenza approssimativa delle stringhe.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Il primo algoritmo di corrispondenza delle stringhe in tempo lineare \u00e8 di&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node7.html#SECTION0070\">Morris e Pratt<\/a>&nbsp;.&nbsp;\u00c8 stato migliorato da&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node8.html#SECTION0080\">Knuth, Morris e Pratt<\/a>&nbsp;.&nbsp;La ricerca si comporta come un processo di riconoscimento da parte dell&#8217;automa, e un carattere del testo viene confrontato con un carattere del pattern non pi\u00f9 di log&nbsp;<sub><\/sub>(&nbsp;<em>m<\/em>&nbsp;+1) (&nbsp;<img loading=\"lazy\" decoding=\"async\" width=\"10\" height=\"12\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gphi.gif\" alt=\"Phi\">\u00e8 il rapporto aureo&nbsp;<img decoding=\"async\" alt=\"rapporto aureo\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/goldenratio.gif\">).&nbsp;Hancart ha dimostrato che questo ritardo di un algoritmo correlato scoperto da Simon non fa pi\u00f9 di 1+log&nbsp;<sub>2&nbsp;<\/sub><em>m<\/em>&nbsp;confronti per carattere di testo.&nbsp;Questi tre algoritmi eseguono al massimo 2&nbsp;<em>n<\/em>&nbsp;-1 confronti di caratteri di testo nel caso peggiore.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La ricerca con un&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node4.html#SECTION0040\">automa finito deterministico<\/a>&nbsp;esegue esattamente&nbsp;<em>n<\/em>&nbsp;ispezioni di caratteri di testo ma richiede uno spazio extra in O(&nbsp;<em>m<\/em><img decoding=\"async\" alt=\"sigma\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/psigma.gif\">&nbsp;).&nbsp;L&#8217;&nbsp;algoritmo&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/fdm.html#SECTION00220\">Forward Dawg Matching<\/a>&nbsp;esegue esattamente lo stesso numero di ispezioni dei caratteri di testo utilizzando l&#8217;automa suffisso del modello.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;&nbsp;algoritmo&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node12.html#SECTION00120\">Apostolico-Crochemore<\/a>&nbsp;\u00e8 un semplice algoritmo che esegue&nbsp;<img decoding=\"async\" alt=\"3\/2\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/troisdemi.gif\"><em>n<\/em>&nbsp;confronti di caratteri di testo nel caso peggiore.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node13.html#SECTION00130\">algoritmo Not So Naive<\/a>&nbsp;\u00e8 un&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node13.html#SECTION00130\">algoritmo<\/a>&nbsp;molto semplice con una complessit\u00e0 temporale quadratica nel caso peggiore, ma richiede una fase di pre-elaborazione in tempo e spazio costanti ed \u00e8 leggermente sublineare nel caso medio.<a>Da destra a sinistra<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;&nbsp;algoritmo di&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node14.html#SECTION00140\">Boyer-Moore<\/a>&nbsp;\u00e8 considerato l&#8217;algoritmo di corrispondenza delle stringhe pi\u00f9 efficiente nelle applicazioni usuali.&nbsp;Una sua versione semplificata (o l&#8217;intero algoritmo) \u00e8 spesso implementata negli editor di testo per i comandi &#8220;cerca&#8221; e &#8220;sostituisci&#8221;.&nbsp;Cole ha dimostrato che il numero massimo di confronti di caratteri \u00e8 strettamente limitato da 3&nbsp;<em>n<\/em>&nbsp;dopo la preelaborazione per modelli non periodici.&nbsp;Ha un tempo quadratico nel caso peggiore per i modelli periodici.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Diverse varianti dell&#8217;algoritmo di Boyer-Moore evitano il suo comportamento quadratico.&nbsp;Le soluzioni pi\u00f9 efficienti in termini di numero di confronti di simboli sono state progettate da&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node16.html#SECTION00160\">Apostolico e Giancarlo<\/a>&nbsp;, Crochemore et alii (&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node15.html#SECTION00150\">Turbo BM<\/a>&nbsp;) e Colussi (&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node17.html#SECTION00170\">Reverse Colussi<\/a>&nbsp;).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I risultati empirici mostrano che le variazioni dell&#8217;algoritmo di Boyer e Moore progettato da Sunday (&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node19.html#SECTION00190\">Quick Search<\/a>&nbsp;) e un algoritmo basato sull&#8217;automa suffisso di Crochemore et alii (&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node23.html#SECTION00230\">Reverse Factor<\/a>&nbsp;e&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node24.html#SECTION00240\">Turbo Reverse Factor<\/a>&nbsp;) sono le pi\u00f9 efficienti nella pratica.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Gli&nbsp;algoritmi&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node20.html#SECTION00200\">Zhu e Takaoka<\/a>&nbsp;e&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/berryravindran.html#SECTION00205\">Berry-Ravindran<\/a>&nbsp;sono varianti dell&#8217;algoritmo Boyer-Moore che richiedono uno spazio extra in&nbsp;<em><strong>O<\/strong><\/em>&nbsp;(&nbsp;<img decoding=\"async\" alt=\"sigma\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/psigma.gif\"><sup>2<\/sup>&nbsp;).<a>In un ordine specifico<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I due primi algoritmi di corrispondenza delle stringhe nello spazio ottimale lineare sono dovuti a&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node25.html#SECTION00250\">Galil-Seiferas<\/a>&nbsp;e Crochemore-Perrin (&nbsp;algoritmo a&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node26.html#SECTION00260\">due vie<\/a>&nbsp;).&nbsp;Dividono il pattern in due parti, prima cercano la parte destra del pattern da sinistra a destra e poi, se non si verifica alcuna discrepanza, cercano la parte sinistra.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Gli algoritmi di&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node10.html#SECTION00100\">Colussi<\/a>&nbsp;e&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node11.html#SECTION00110\">Galil-Giancarlo<\/a>&nbsp;suddividono l&#8217;insieme delle posizioni del pattern in due sottoinsiemi.&nbsp;Prima cercano i caratteri del modello le cui posizioni sono nel primo sottoinsieme da sinistra a destra e poi, se non si verifica una mancata corrispondenza, cercano i caratteri rimanenti da sinistra a destra.&nbsp;L&#8217;algoritmo Colussi \u00e8 un miglioramento rispetto all&#8217;algoritmo Knuth-Morris-Pratt ed esegue al massimo&nbsp;<img decoding=\"async\" alt=\"3\/2\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/troisdemi.gif\"><em>n<\/em>&nbsp;confronti di caratteri di testo nel caso peggiore.&nbsp;L&#8217;algoritmo Galil-Giancarlo migliora l&#8217;algoritmo Colussi in un caso speciale che gli consente di eseguire al massimo&nbsp;<img decoding=\"async\" alt=\"4\/3\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/quattiers.gif\"><em>n<\/em>&nbsp;confronti di caratteri di testo nel caso peggiore.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Gli&nbsp;algoritmi di&nbsp;Sunday&#8217;s&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node28.html#SECTION00280\">Optimal Mismatch<\/a>&nbsp;e&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node29.html#SECTION00290\">Maximal Shift<\/a>&nbsp;ordinano le posizioni del modello rispettivamente in base alla frequenza dei caratteri e allo spostamento iniziale.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node31.html#SECTION00310\">Gli<\/a>&nbsp;algoritmi&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node31.html#SECTION00310\">Skip Search<\/a>&nbsp;,&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node32.html#SECTION00320\">KMP Skip Search<\/a>&nbsp;e&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node33.html#SECTION00330\">Alpha Skip Search<\/a>&nbsp;di Charras (&nbsp;<em>et alii<\/em>&nbsp;) utilizzano i bucket per determinare le posizioni iniziali sul modello nel testo.<a>In qualsiasi ordine<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;&nbsp;algoritmo di&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node18.html#SECTION00180\">Horspool<\/a>&nbsp;\u00e8 una variante dell&#8217;algoritmo di&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node14.html#SECTION00140\">Boyer-Moore<\/a>&nbsp;, utilizza una delle sue funzioni shift e l&#8217;ordine in cui vengono eseguiti i confronti dei caratteri del testo \u00e8 irrilevante.&nbsp;Questo vale anche per tutte le altre varianti come la&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node19.html#SECTION00190\">Quick Search<\/a>&nbsp;di Sunday,&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/tunedbm.html#SECTION00195\">Tuned Boyer-Moore<\/a>&nbsp;di Hume e Sunday, l&#8217;&nbsp;algoritmo di&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node21.html#SECTION00210\">Smith<\/a>&nbsp;e l&#8217;&nbsp;algoritmo di&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node22.html#SECTION00220\">Raita<\/a>&nbsp;.<a>Definizioni<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prenderemo in considerazione ricerche pratiche.&nbsp;Assumeremo che l&#8217;alfabeto sia l&#8217;insieme dei codici ASCII o un suo sottoinsieme.&nbsp;Gli algoritmi sono presentati in linguaggio di programmazione C, quindi per una parola&nbsp;<em>w<\/em>&nbsp;di lunghezza&nbsp;<img decoding=\"async\" alt=\"ell\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/ell.gif\">i caratteri sono&nbsp;<em>w<\/em>&nbsp;[0], &#8230; ,&nbsp;<em>w<\/em>&nbsp;[&nbsp;<img decoding=\"async\" alt=\"ell\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/ell.gif\">-1] e&nbsp;<em>w<\/em>&nbsp;[&nbsp;<img decoding=\"async\" alt=\"ell\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/ell.gif\">] contenevano il carattere di fine speciale (carattere nullo) che non pu\u00f2 verificarsi da nessuna parte all&#8217;interno di ogni parola ma alla fine.&nbsp;Entrambe le parole, il motivo e il testo risiedono nella memoria principale.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Introduciamo alcune definizioni.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una parola&nbsp;<em>u<\/em>&nbsp;\u00e8 un&nbsp;<em>prefisso<\/em>&nbsp;di una parola&nbsp;<em>w<\/em>&nbsp;se esiste una parola&nbsp;<em>v<\/em>&nbsp;(possibilmente vuota) tale che&nbsp;<em>w<\/em>&nbsp;=&nbsp;<em>uv<\/em>&nbsp;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una parola&nbsp;<em>v<\/em>&nbsp;\u00e8 un&nbsp;<em>suffisso<\/em>&nbsp;di una parola&nbsp;<em>w<\/em>&nbsp;se esiste una parola&nbsp;<em>u<\/em>&nbsp;(possibilmente vuota) tale che&nbsp;<em>w<\/em>&nbsp;=&nbsp;<em>uv<\/em>&nbsp;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una parola&nbsp;<em>z<\/em>&nbsp;\u00e8 una&nbsp;<em>sottostringa<\/em>&nbsp;o una&nbsp;<em>sottoparola<\/em>&nbsp;o un&nbsp;<em>fattore<\/em>&nbsp;di una parola&nbsp;<em>w<\/em>&nbsp;se esistono due parole&nbsp;<em>u<\/em>&nbsp;e&nbsp;<em>v<\/em>&nbsp;(possibilmente vuote) tali che&nbsp;<em>w<\/em>&nbsp;=&nbsp;<em>uzv<\/em>&nbsp;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Un intero&nbsp;<em>p<\/em>&nbsp;\u00e8 un&nbsp;<em>periodo<\/em>&nbsp;di una parola&nbsp;<em>w<\/em>&nbsp;if for&nbsp;<em>i<\/em>&nbsp;, 0 &nbsp;&nbsp;<img decoding=\"async\" alt=\"leq\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/leq.gif\">&nbsp;<em>i<\/em>&nbsp;&lt;&nbsp;<em>m<\/em>&nbsp;&#8211;&nbsp;<em>p<\/em>&nbsp;,&nbsp;<em>w<\/em>&nbsp;[&nbsp;<em>i<\/em>&nbsp;]=&nbsp;<em>w<\/em>&nbsp;[&nbsp;<em>i<\/em>&nbsp;+&nbsp;<em>p<\/em>&nbsp;].&nbsp;Il periodo pi\u00f9 piccolo di&nbsp;<em>w<\/em>&nbsp;\u00e8 chiamato&nbsp;<em>periodo<\/em>&nbsp;, \u00e8 indicato con&nbsp;<em>per<\/em>&nbsp;(&nbsp;<em>w<\/em>&nbsp;).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una parola&nbsp;<em>w<\/em>&nbsp;di lunghezza&nbsp;<img decoding=\"async\" alt=\"ell\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/ell.gif\">\u00e8&nbsp;<em>periodica<\/em>&nbsp;se la lunghezza del suo periodo pi\u00f9 piccolo \u00e8 minore o uguale a&nbsp;<img decoding=\"async\" alt=\"ell\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/ell.gif\">\/2, altrimenti \u00e8&nbsp;<em>non periodica<\/em>&nbsp;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una parola&nbsp;<em>w<\/em>&nbsp;\u00e8&nbsp;<em>fondamentale<\/em>&nbsp;se non pu\u00f2 essere scritta come una potenza di un&#8217;altra parola: non esistono n\u00e9 una parola&nbsp;<em>z<\/em>&nbsp;n\u00e9 un intero&nbsp;<em>k<\/em>&nbsp;tale che&nbsp;<em>w<\/em>&nbsp;=&nbsp;<em>z&nbsp;<sup>k<\/sup><\/em>&nbsp;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una parola&nbsp;<em>z<\/em>&nbsp;\u00e8 un&nbsp;<em>bordo<\/em>&nbsp;di una parola&nbsp;<em>w<\/em>&nbsp;se esistono due parole&nbsp;<em>u<\/em>&nbsp;e&nbsp;<em>v<\/em>&nbsp;tali che&nbsp;<em>w<\/em>&nbsp;=&nbsp;<em>uz<\/em>&nbsp;=&nbsp;<em>zv<\/em>&nbsp;,&nbsp;<em>z<\/em>&nbsp;\u00e8 sia un prefisso che un suffisso di&nbsp;<em>w<\/em>&nbsp;.&nbsp;Nota che in questo caso |&nbsp;<em>u<\/em>&nbsp;|=|&nbsp;<em>v<\/em>&nbsp;|&nbsp;\u00e8 un periodo di&nbsp;<em>w<\/em>&nbsp;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Il rovescio di una parola&nbsp;<em>w<\/em>&nbsp;di lunghezza&nbsp;<img decoding=\"async\" alt=\"ell\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/ell.gif\">indicata con&nbsp;<em>w&nbsp;<sup>R<\/sup><\/em>&nbsp;\u00e8 l&#8217;immagine speculare di&nbsp;<em>w<\/em>&nbsp;;&nbsp;<em>w&nbsp;<sup>R<\/sup><\/em>&nbsp;=&nbsp;<em>w<\/em>&nbsp;[&nbsp;<img decoding=\"async\" alt=\"ell\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/ell.gif\">-1]&nbsp;<em>w<\/em>&nbsp;[&nbsp;<img decoding=\"async\" alt=\"ell\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/ell.gif\">-2] &#8230;&nbsp;<em>w<\/em>&nbsp;[1]&nbsp;<em>w<\/em>&nbsp;[0].<br>Un Automa Finito Deterministico (DFA)&nbsp;A&nbsp;\u00e8 un quadruplo (&nbsp;<em><strong>Q<\/strong><\/em>&nbsp;, q&nbsp;<sub>0<\/sub>&nbsp;,&nbsp;<em><strong>T<\/strong><\/em>&nbsp;,&nbsp;<em><strong>E<\/strong><\/em>&nbsp;) dove:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><img decoding=\"async\" alt=\"\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/hand.gif\">&nbsp;<\/td><td><em><strong>Q<\/strong><\/em>&nbsp;\u00e8 un insieme finito di stati;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><img decoding=\"async\" alt=\"\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/hand.gif\">&nbsp;<\/td><td>q&nbsp;<sub>0<\/sub>&nbsp;in&nbsp;<em><strong>Q<\/strong><\/em>&nbsp;\u00e8 lo stato iniziale;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><img decoding=\"async\" alt=\"\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/hand.gif\">&nbsp;<\/td><td><em><strong>T<\/strong><\/em>&nbsp;, sottoinsieme di<em><strong>&nbsp;Q<\/strong><\/em>&nbsp;, \u00e8 l&#8217;insieme degli stati terminali;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><img decoding=\"async\" alt=\"\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/hand.gif\">&nbsp;<\/td><td><em><strong>E,<\/strong><\/em>&nbsp;sottoinsieme di (<em><strong>&nbsp;Q<\/strong><\/em>&nbsp;.<img decoding=\"async\" alt=\"Sigma\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif\">.<em><strong>&nbsp;Q<\/strong><\/em>&nbsp;), \u00e8 l&#8217;insieme delle transizioni.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">La lingua&nbsp;<em><strong>L<\/strong><\/em>&nbsp;(&nbsp;A&nbsp;) definita da&nbsp;A&nbsp;\u00e8 il seguente insieme:<br><img decoding=\"async\" alt=\"\" src=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/lang1.gif\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per ogni algoritmo esatto di string-matching presentato nel presente libro diamo prima le sue caratteristiche principali, poi abbiamo spiegato come funziona prima di dare il suo codice C.&nbsp;Successivamente mostriamo il suo comportamento su un tipico esempio dove&nbsp;<em>x<\/em>&nbsp;=GCAGAGAG&nbsp;<em>ey<\/em>&nbsp;=GCATCGCAGAGAGTATACAGTACG.&nbsp;Infine diamo un elenco di riferimenti dove il lettore trover\u00e0 presentazioni e dimostrazioni pi\u00f9 dettagliate dell&#8217;algoritmo.&nbsp;Ad ogni tentativo, le corrispondenze vengono materializzate in grigio chiaro mentre le discrepanze vengono mostrate in grigio scuro.&nbsp;Un numero indica l&#8217;ordine in cui vengono eseguiti i confronti dei caratteri, ad eccezione degli algoritmi che utilizzano gli automi, dove il numero rappresenta lo stato raggiunto dopo l&#8217;ispezione dei caratteri.<a>Implementazione<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In questo libro, usiamo stringhe C e assumiamo che una stringa di lunghezza&nbsp;<em>m<\/em>&nbsp;contenga un&nbsp;simbolo (&nbsp;<em>m<\/em>&nbsp;+1)-esimo (di solito assegnato con il valore &#8216;\\0&#8217;).&nbsp;In caso contrario, alcune implementazioni di algoritmi potrebbero andare in crash quando si accede a una posizione appena oltre l&#8217;effettivo ultimo carattere di una stringa.&nbsp;(Grazie a David B. Trout di Software Development Laboratories per aver indicato questo punto particolare).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In questo libro useremo strumenti classici.&nbsp;Uno di questi \u00e8 un elenco collegato di numeri interi.&nbsp;Sar\u00e0 definito in C come segue:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  struct _cell{ \n    int elemento; \n    struct _cell *next; \n  }; \n \n  typedef struct _cell *Lista;\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Altre strutture importanti sono gli automi e in particolare gli automi suffissi (vedi&nbsp;<a href=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/node23.html\">capitolo 22<\/a>&nbsp;).&nbsp;Fondamentalmente gli automi sono grafi diretti.&nbsp;Useremo la seguente interfaccia per manipolare gli automi:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  Grafico newGraph(int v, int e); \n  Grafico newAutomaton(int v, int e); \n  Grafico newSuffixAutomaton(int v, int e); \n  int newVertex(Grafico g); \n  int getInitial(Grafico g); \n  isTerminal booleano(Grafico g, int v); \n  void setTerminal(Grafico g, int v); \n  int getTarget(Graph g, int v, unsigned char c); \n  void setTarget(Graph g, int v, unsigned char c, int t); \n  int getSuffixLink(Grafico g, int v); \n  void setSuffixLink(Graph g, int v, int s); \n  int getLength(Grafico g, int v); \n  void setLength(Graph g, int v, int ell); \n  int getPosition(Grafico g, int v); \n  void setPosition(Grafico g, int v, int p);\n  int getShift(Graph g, int v, unsigned char c);\n  void setShift(Graph g, int v, unsigned char c, int s); \n  void copyVertex(Graph g, int target, int source);\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Segue una possibile implementazione di questa interfaccia.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  struct _graph { \n    int vertexNumber, \n        edgeNumber, \n        vertexCounter, \n        initial, \n        *terminal, \n        *target, \n        *suffixLink, \n        *length, \n        *position, \n        *shift; \n  }; \n  \n  typedef struct _graph *Graph; \n  typedef int booleano; \n   \n#define UNDEFINED -1 \n  \n\/* restituisce una nuova struttura dati per \n   un grafo con v vertici ed e \narchi *\/ Graph newGraph(int v, int e) { \n   Graph g; \n\n   g = (Graph)calloc(1, sizeof(struct _graph)); \n   if (g == NULL) \n      error(\"newGraph\"); \n   g-&gt;numero vertice = v;\n   g-&gt;edgeNumber = e; \n   g-&gt;iniziale = 0; \n   g-&gt;vertexCounter = 1; \n   ritorno(g); \n} \n\n\n\/* restituisce una nuova struttura dati per \n   un automa con v vertici ed e bordi *\/ \nGraph newAutomaton(int v, int e) { \n   Graph aut; \n\n   aut = newGraph(v, e); \n   aut-&gt;target = (int *)calloc(e, sizeof(int)); \n   if (aut-&gt;target == NULL) \n      error(\"newAutomaton\"); \n   aut-&gt;terminal = (int *)calloc(v, sizeof(int)); \n   if (aut-&gt;terminal == NULL) \n      error(\"newAutomaton\"); \n   ritorno(auto); \n} \n\n\n\/* restituisce una nuova struttura dati per \n   un automa suffisso con v vertici ed e bordi *\/\nGraph newSuffixAutomaton(int v, int e) { \n   Graph aut; \n\n   aut = nuovoAutoma(v,e);\n   memset(aut-&gt;target, UNDEFINED, e*sizeof(int)); \n   aut-&gt;suffixLink = (int *)calloc(v, sizeof(int)); \n   if (aut-&gt;suffixLink == NULL) \n      error(\"newSuffixAutomaton\"); \n   aut-&gt;lunghezza = (int *)calloc(v, sizeof(int)); \n   if (aut-&gt;length == NULL) \n      error(\"newSuffixAutomaton\"); \n   aut-&gt;posizione = (int *)calloc(v, sizeof(int)); \n   if (aut-&gt;position == NULL) \n      error(\"newSuffixAutomaton\"); \n   aut-&gt;shift = (int *)calloc(e, sizeof(int)); \n   if (aut-&gt;shift == NULL) \n      error(\"newSuffixAutomaton\"); \n   ritorno(auto);\n \n  \n   un trie con v vertici ed e bordi *\/ \nGraph newTrie(int v,\n  \n   aut = newAutomaton(v, e); \n   memset(aut-&gt;target, UNDEFINED, e*sizeof(int)); \n   aut-&gt;suffixLink = (int *)calloc(v, sizeof(int)); \n   if (aut-&gt;suffixLink == NULL) \n      errore(\"newTrie\"); \n   aut-&gt;lunghezza = (int *)calloc(v, sizeof(int)); \n   if (aut-&gt;length == NULL) \n      error(\"newTrie\"); \n   aut-&gt;posizione = (int *)calloc(v, sizeof(int)); \n   if (aut-&gt;position == NULL) \n      error(\"newTrie\"); \n   aut-&gt;shift = (int *)calloc(e, sizeof(int)); \n   if (aut-&gt;shift == NULL) \n      error(\"newTrie\"); \n   ritorno(auto);\n\n \n   if (g != NULL &amp;&amp; g-&gt;\n      return(g-&gt;vertexCounter++); \n   errore(\"nuovo vertice\"); \n} \n\n\n\/* restituisce il vertice iniziale del grafo g *\/ \nint getInitial(Graph g) { \n   if (g != NULL) \n      return(g-&gt;initial); \n   errore(\"getInitial\"); \n} \n\n\n\/* restituisce true se il vertice v \u00e8 terminale nel grafico g *\/ \nbooleano isTerminal(Graph g, int v) { \n   if (g != NULL &amp;&amp; g-&gt;terminal != NULL &amp;&amp; \n       v &lt; g-&gt;vertexNumber) \n      return(g -&gt; terminale[v]); \n   error(\"isTerminal\"); \n} \n\n\n\/* imposta il vertice v come terminale nel grafico g *\/ \nvoid setTerminal(Graph g, int v) { \n       v &lt; g-&gt;vertexNumber) \n      g-&gt;terminal[v] = 1;\n      error(\"isTerminal\"); \n} \n\n\n\/* restituisce il target del bordo dal vertice v \n   etichettato dal carattere c nel grafico g *\/ \nint getTarget(Graph g, int v, unsigned char c) { \n   if (g != NULL &amp;&amp; g-&gt;target != NULL &amp;&amp; \n       v &lt; g-&gt;NumeroVertice &amp;&amp; v*c &lt; g-&gt;NumeroEdge) \n      return(g-&gt;target[v*(g-&gt;NumeroEdge\/g-&gt;NumeroVertice) + \n                       c]); \n   errore(\"getTarget\"); \n} \n\n\n\/* aggiunge il bordo dal vertice v al vertice t \n   etichettato dal carattere c nel grafico g *\/ \nvoid setTarget(Graph g, int v, unsigned char c, int t) { \n   if (g != NULL &amp;&amp; g-&gt;target ! = NULL &amp;&amp;\n       v*c &lt;= g-&gt;edgeNumber &amp;&amp; t &lt; g-&gt;vertexNumber) \n      g-&gt;target[v*(g-&gt;edgeNumber\/g-&gt;vertexNumber) + c] = t; \n   else \n      errore(\"setTarget\"); \n} \n\n\n\/* restituisce il collegamento suffisso del vertice v nel grafico g *\/ \nint getSuffixLink(Graph g, int v) { \n   if (g != NULL &amp;&amp; g-&gt;suffixLink != NULL &amp;&amp; \n       v &lt; g-&gt;vertexNumber) \n      return(g -&gt;suffissoLink[v]); \n   error(\"getSuffixLink\"); \n} \n\n\n\/* imposta il collegamento del suffisso del vertice v \n   al vertice s nel grafico g *\/ \nvoid setSuffixLink(Graph g, int v, int s) { \n   if (g != NULL &amp;&amp; g-&gt;suffixLink != NULL &amp;&amp; \n       v &lt; g- &gt;Numero vertice &amp;&amp; \n      s &lt; g-&gt;vertexNumber) g-&gt;suffixLink[v] = s; \n   altro\n      error(\"setSuffixLink\"); \n}\n\n\n\/* restituisce la lunghezza del vertice v nel grafico g *\/ \nint getLength(Graph g, int v) { \n   if (g != NULL &amp;&amp; g-&gt;length != NULL &amp;&amp; \n       v &lt; g-&gt;vertexNumber) \n      return(g-&gt; lunghezza[v]); \n   errore(\"getLength\"); \n} \n\n\n\/* imposta la lunghezza del vertice v \nsull'intero ell nel grafico g *\/ void setLength(Graph g, int v, int ell) { \n   if (g != NULL &amp;&amp; g-&gt;length != NULL &amp;&amp; \n       v &lt; g-&gt; vertexNumber) \n      g-&gt;lunghezza[v] = ell; \n   else \n      errore(\"setLength\"); \n} \n\n\n\/* restituisce la posizione del vertice v nel grafico g *\/ \nint getPosition(Graph g, int v) { \n       v &lt; g-&gt;\n   errore(\"getPosition\"); \n} \n\n\n\/* imposta la lunghezza del vertice v all'intero ell nel grafico g *\/ \nvoid setPosition(Graph g, int v, int p) { \n   if (g != NULL &amp;&amp; g-&gt;position != NULL &amp;&amp; \n       v &lt; g-&gt; vertexNumber) \n      g-&gt;posizione[v] = p; \n   else \n      errore(\"setPosition\"); \n} \n\n\n\/* restituisce lo spostamento del bordo dal vertice v \n   etichettato dal carattere c nel grafico g *\/ \nint getShift(Graph g, int v, unsigned char c) { \n   if (g != NULL &amp;&amp; g-&gt;shift != NULL &amp;&amp; \n       v &lt; g-&gt;NumeroVertice &amp;&amp; v*c &lt; g-&gt;NumeroEdge) \n      return(g-&gt;shift[v*(g-&gt;NumeroEdge\/g-&gt;Numerovertice) +\n   errore(\"getShift\"); \n} \n\n\n\/* imposta lo spostamento del bordo dal vertice v \n   etichettato dal carattere c all'intero s nel grafico g *\/ \nvoid setShift(Graph g, int v, unsigned char c, int s) { \n   if (g != NULL &amp;&amp; g- &gt;shift != NULL &amp;&amp; \n       v &lt; g-&gt;vertexNumber &amp;&amp; v*c &lt;= g-&gt;edgeNumber) \n      g-&gt;shift[v*(g-&gt;edgeNumber\/g-&gt;vertexNumber) + c] = s; \n   else \n      errore(\"setShift\"); \n} \n\n\n\/* copia tutte le caratteristiche della sorgente del \n   vertice nella destinazione del vertice nel grafico g *\/ \nvoid copyVertex(Graph g, int target, int source) { \n   if (g != NULL &amp;&amp; target &lt; g-&gt;vertexNumber &amp;&amp; \n       source &lt; g-&gt; \n         memcpy(g-&gt;\n                g-&gt;target + \n                source*(g-&gt;edgeNumber\/g-&gt;vertexNumber), \n                (g-&gt;edgeNumber\/g-&gt;vertexNumber)* \n                sizeof(int)); \n      if (g-&gt;shift != NULL) \n         memcpy(g-&gt;shift + \n                target*(g-&gt;edgeNumber\/g-&gt;vertexNumber), \n                g-&gt;shift + \n                source*(g-&gt;edgeNumber\/g-&gt;vertexNumber), \n                g-&gt;edgeNumber\/g-&gt;vertexNumber)* \n                sizeof(int)); \n      if (g-&gt;terminal != NULL) \n         g-&gt;terminal[target] = g-&gt;terminal[source]; \n      if (g-&gt;suffixLink != NULL) \n         g-&gt;length[target] = g-&gt; \n         g-&gt;suffixLink[target] = g-&gt;\n      if (g-&gt;lunghezza != NULL) \n      if (g-&gt;posizione != NULL) \n         g-&gt;posizione[destinazione] = g-&gt;posizione[sorgente]; \n   } \n   else \n      errore(\"copyVertex\"); \n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><em><small>e-mails: {<a href=\"mailto:Christian.Charras@laposte.net\">Christian.Charras<\/a>,&nbsp;<a href=\"mailto:Thierry.Lecroq@laposte.net\">Thierry.Lecroq<\/a>} @laposte.net<br>Tue Jan 14 15:03:31 MET 1997<\/small><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>introduzione La corrispondenza delle stringhe \u00e8 un argomento molto importante nel pi\u00f9 ampio dominio dell&#8217;elaborazione del testo.&nbsp;Gli algoritmi di corrispondenza delle stringhe sono componenti di base utilizzati nelle implementazioni di software pratici esistenti nella maggior&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1421","page","type-page","status-publish"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.7 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>introduzione - Coupontoaster Blog<\/title>\n<meta name=\"description\" content=\"introduzione La corrispondenza delle stringhe \u00e8 un argomento molto importante nel pi\u00f9 ampio dominio dell&#039;elaborazione del testo.&nbsp;Gli algoritmi di\" \/>\n<meta name=\"robots\" content=\"noindex, nofollow\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"introduzione - Coupontoaster Blog\" \/>\n<meta property=\"og:description\" content=\"introduzione La corrispondenza delle stringhe \u00e8 un argomento molto importante nel pi\u00f9 ampio dominio dell&#039;elaborazione del testo.&nbsp;Gli algoritmi di\" \/>\n<meta property=\"og:url\" content=\"https:\/\/coupontoaster.com\/blog\/introduzione\/\" \/>\n<meta property=\"og:site_name\" content=\"Coupontoaster Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/coupontoaster\/\" \/>\n<meta property=\"article:modified_time\" content=\"2023-04-28T13:17:40+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@coupontoaster\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"18 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/coupontoaster.com\/blog\/introduzione\/\",\"url\":\"https:\/\/coupontoaster.com\/blog\/introduzione\/\",\"name\":\"introduzione - Coupontoaster Blog\",\"isPartOf\":{\"@id\":\"https:\/\/coupontoaster.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/coupontoaster.com\/blog\/introduzione\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/coupontoaster.com\/blog\/introduzione\/#primaryimage\"},\"thumbnailUrl\":\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif\",\"datePublished\":\"2021-08-25T10:34:49+00:00\",\"dateModified\":\"2023-04-28T13:17:40+00:00\",\"description\":\"introduzione La corrispondenza delle stringhe \u00e8 un argomento molto importante nel pi\u00f9 ampio dominio dell'elaborazione del testo.&nbsp;Gli algoritmi di\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/coupontoaster.com\/blog\/introduzione\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/coupontoaster.com\/blog\/introduzione\/#primaryimage\",\"url\":\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif\",\"contentUrl\":\"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif\"},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/coupontoaster.com\/blog\/#website\",\"url\":\"https:\/\/coupontoaster.com\/blog\/\",\"name\":\"Coupontoaster Blog\",\"description\":\"We Appreciate The Quality Content\",\"publisher\":{\"@id\":\"https:\/\/coupontoaster.com\/blog\/#organization\"},\"alternateName\":\"Coupontoaster\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/coupontoaster.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/coupontoaster.com\/blog\/#organization\",\"name\":\"Coupontoaster\",\"alternateName\":\"Coupontoaster.com\",\"url\":\"https:\/\/coupontoaster.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/coupontoaster.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/coupontoaster.com\/blog\/wp-content\/uploads\/2024\/01\/coupontoaster_logo.webp\",\"contentUrl\":\"https:\/\/coupontoaster.com\/blog\/wp-content\/uploads\/2024\/01\/coupontoaster_logo.webp\",\"width\":291,\"height\":62,\"caption\":\"Coupontoaster\"},\"image\":{\"@id\":\"https:\/\/coupontoaster.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/coupontoaster\/\",\"https:\/\/x.com\/coupontoaster\"]}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"introduzione - Coupontoaster Blog","description":"introduzione La corrispondenza delle stringhe \u00e8 un argomento molto importante nel pi\u00f9 ampio dominio dell'elaborazione del testo.&nbsp;Gli algoritmi di","robots":{"index":"noindex","follow":"nofollow"},"og_locale":"en_US","og_type":"article","og_title":"introduzione - Coupontoaster Blog","og_description":"introduzione La corrispondenza delle stringhe \u00e8 un argomento molto importante nel pi\u00f9 ampio dominio dell'elaborazione del testo.&nbsp;Gli algoritmi di","og_url":"https:\/\/coupontoaster.com\/blog\/introduzione\/","og_site_name":"Coupontoaster Blog","article_publisher":"https:\/\/www.facebook.com\/coupontoaster\/","article_modified_time":"2023-04-28T13:17:40+00:00","og_image":[{"url":"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif","type":"","width":"","height":""}],"twitter_card":"summary_large_image","twitter_site":"@coupontoaster","twitter_misc":{"Est. reading time":"18 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/coupontoaster.com\/blog\/introduzione\/","url":"https:\/\/coupontoaster.com\/blog\/introduzione\/","name":"introduzione - Coupontoaster Blog","isPartOf":{"@id":"https:\/\/coupontoaster.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/coupontoaster.com\/blog\/introduzione\/#primaryimage"},"image":{"@id":"https:\/\/coupontoaster.com\/blog\/introduzione\/#primaryimage"},"thumbnailUrl":"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif","datePublished":"2021-08-25T10:34:49+00:00","dateModified":"2023-04-28T13:17:40+00:00","description":"introduzione La corrispondenza delle stringhe \u00e8 un argomento molto importante nel pi\u00f9 ampio dominio dell'elaborazione del testo.&nbsp;Gli algoritmi di","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/coupontoaster.com\/blog\/introduzione\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/coupontoaster.com\/blog\/introduzione\/#primaryimage","url":"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif","contentUrl":"http:\/\/www-igm.univ-mlv.fr\/~lecroq\/string\/images\/gsigma.gif"},{"@type":"WebSite","@id":"https:\/\/coupontoaster.com\/blog\/#website","url":"https:\/\/coupontoaster.com\/blog\/","name":"Coupontoaster Blog","description":"We Appreciate The Quality Content","publisher":{"@id":"https:\/\/coupontoaster.com\/blog\/#organization"},"alternateName":"Coupontoaster","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/coupontoaster.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/coupontoaster.com\/blog\/#organization","name":"Coupontoaster","alternateName":"Coupontoaster.com","url":"https:\/\/coupontoaster.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/coupontoaster.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/coupontoaster.com\/blog\/wp-content\/uploads\/2024\/01\/coupontoaster_logo.webp","contentUrl":"https:\/\/coupontoaster.com\/blog\/wp-content\/uploads\/2024\/01\/coupontoaster_logo.webp","width":291,"height":62,"caption":"Coupontoaster"},"image":{"@id":"https:\/\/coupontoaster.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/coupontoaster\/","https:\/\/x.com\/coupontoaster"]}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/coupontoaster.com\/blog\/wp-json\/wp\/v2\/pages\/1421","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coupontoaster.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/coupontoaster.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/coupontoaster.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coupontoaster.com\/blog\/wp-json\/wp\/v2\/comments?post=1421"}],"version-history":[{"count":0,"href":"https:\/\/coupontoaster.com\/blog\/wp-json\/wp\/v2\/pages\/1421\/revisions"}],"wp:attachment":[{"href":"https:\/\/coupontoaster.com\/blog\/wp-json\/wp\/v2\/media?parent=1421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}