aggiunta classe con algoritmi di pattern matching
This commit is contained in:
94
src/it/algoritmi/test/PatternMatching.java
Normal file
94
src/it/algoritmi/test/PatternMatching.java
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
package it.algoritmi.test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class PatternMatching {
|
||||||
|
|
||||||
|
/** Restituisce l'indice minimo in cui inizia pattern nel testo (oppure -1). */
|
||||||
|
public static int findBrute(char[] text, char[] pattern) {
|
||||||
|
int n = text.length;
|
||||||
|
int m = pattern.length;
|
||||||
|
for (int i = 0; i <= n - m; ++i) { // prova tutti gli indici iniziali nel testo
|
||||||
|
int k = 0;
|
||||||
|
while (k < m && text[i + k] == pattern[k]) // il k-esimo carattere corrisponde
|
||||||
|
++k;
|
||||||
|
if (k == m) // se lo abbiamo raggiunto la fine del pattern
|
||||||
|
return i; // la sottostringa text[i..i+m-1] corrisponde al pattern
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Restituisce l'indice in cui inizia pattern nel testo (oppure -1). */
|
||||||
|
public static int findBoyerMoore(char[] text, char[] pattern) {
|
||||||
|
int n = text.length;
|
||||||
|
int m = pattern.length;
|
||||||
|
if (m == 0)
|
||||||
|
return 0; // ricerca banale di una stringa vuota
|
||||||
|
Map<Character, Integer> last = new HashMap<>(); // la mappa della funzione 'last'
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
last.put(text[i], -1); // usa -1 come default per tutti i caratteri del testo
|
||||||
|
for (int k = 0; k < m; k++)
|
||||||
|
last.put(pattern[k], k); // l'occorrenza più a destra sarà l'ultima memorizzata
|
||||||
|
// inizia con la fine del pattern allineata con l'indice m-1 del testo
|
||||||
|
int i = m - 1; // indice nel testo
|
||||||
|
int k = m - 1; // indice nel pattern
|
||||||
|
while (i < n) {
|
||||||
|
if (text[i] == pattern[k]) { // trovato un carattere che corrisponde
|
||||||
|
if (k == 0)
|
||||||
|
return i; // trovato un intero pattern che corrisponde
|
||||||
|
i--;
|
||||||
|
k--;
|
||||||
|
} else {
|
||||||
|
i += m - Math.min(k, 1 + last.get(text[i])); // decide come fare il salto
|
||||||
|
k = m - 1; // riparte dalla fine del pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1; // ricerca fallita
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Restituisce l'indice minimo in cui inizia pattern nel testo (oppure -1). */
|
||||||
|
public static int findKMP(char[] text, char[] pattern) {
|
||||||
|
int n = text.length;
|
||||||
|
int m = pattern.length;
|
||||||
|
if (m == 0) // ricerca banale di una stringa vuota
|
||||||
|
return 0;
|
||||||
|
int[] fail = computeFailKMP(pattern); // funzione calcolata da un metodo privato
|
||||||
|
int j = 0; // indice del testo
|
||||||
|
int k = 0; // indice del pattern
|
||||||
|
while (j < n) {
|
||||||
|
if (text[j] == pattern[k]) { // il pattern[0...k] corrisponde fin qui
|
||||||
|
if (k == m - 1)
|
||||||
|
return j - m + 1; // corrispondenza completa
|
||||||
|
j++; // altrimenti cerca di estendere la corrispondenza
|
||||||
|
k++;
|
||||||
|
} else if (k > 0) {
|
||||||
|
k = fail[k - 1]; // riutilizza il suffisso di P[0...k-1]
|
||||||
|
} else {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1; // ricerca fallita
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] computeFailKMP(char[] pattern) {
|
||||||
|
int m = pattern.length;
|
||||||
|
int[] fail = new int[m]; // tutte le sovrapposizioni cosi sono uguali a zero
|
||||||
|
int j = 1;
|
||||||
|
int k = 0;
|
||||||
|
while (j < m) { // in questo passo calcola fail[j], se non è zero
|
||||||
|
if (pattern[j] == pattern[k]) { // finora k+1 caratteri corrispondono
|
||||||
|
fail[j] = k + 1;
|
||||||
|
j++;
|
||||||
|
k++;
|
||||||
|
} else if (k > 0) { // k segue un prefisso che corrisponde
|
||||||
|
k = fail[k - 1];
|
||||||
|
} else {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user