-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKMPMatcher.java
More file actions
78 lines (67 loc) · 3.07 KB
/
KMPMatcher.java
File metadata and controls
78 lines (67 loc) · 3.07 KB
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
package Esame;
import java.util.ArrayList;
import java.util.List;
public class KMPMatcher {
// creo l'array LPS per evitare confronti ripetuti
// ogni elemento lps[i] rappresenta la lunghezza del prefisso più lungo che è anche suffisso nella sottostringa pattern[0..i]
private int[] computeLPSArray(String pattern) {
int m = pattern.length();
int[] lps = new int[m];
int len = 0; // lunghezza del prefisso-suffisso più lungo trovato finora
int i = 1; // indice per scorrere l'input patendo dal secondo carattere
// nessun prefisso-suffisso possibile per il primo carattere
lps[0] = 0;
while (i < m) {
// verifico se il prefisso della sottostringa considerata del pattern è anche suffisso
if (pattern.charAt(i) == pattern.charAt(len)) {
// len rappresenta un indice (che va da 0 a len-1), incrementiamo di 1 per memorizzare in lps la lunghezza effettiva del prefisso-suffisso
len++;
lps[i] = len;
// incremento i per continuare la ricerca del pattern
i++;
} else {
// se si verifica un mismatch, invece di ricominciare da capo, ripartiamo dall'indice dell'ultimo prefisso-suffisso più lungo trovato (-1 perchè altrimenti len indica la lunghezza, non l'indice)
if (len != 0) {
len = lps[len - 1]; // torno indietro nel pattern
} else {
lps[i] = 0;
i++;
}
}
}
// resituisco l'array popolato con i salti intelligenti per ogni prefisso-suffisso nel pattern
return lps;
}
// cerca tutte le occorrenze del pattern in una stringa di input
// restituisce una lista di indici, cioè il punto di inizio dei pattern riconosciuti el testo
public List<Integer> search(String text, String pattern) {
List<Integer> result = new ArrayList<>();
int n = text.length();
int m = pattern.length();
// pattern vuoto, testo vuoto o pattern più lungo del testo
if (m == 0 || n == 0 || m > n) return result;
// calcolo l'LPS in base al pattern specificato
int[] lps = computeLPSArray(pattern);
int i = 0; // indice nel testo
int j = 0; // indice nel pattern
while (i < n) {
if (text.charAt(i) == pattern.charAt(j)) {
i++;
j++;
}
// match completo del pattern
if (j == m) {
result.add(i - j); // pattern trovato
j = lps[j - 1]; // cerco match sovrapposti
} else if (i < n && text.charAt(i) != pattern.charAt(j)) {
if (j != 0) {
j = lps[j - 1]; // salta nel pattern
} else {
i++;
}
}
}
// restituisce la lista delle posizioni in cui il pattern è stato trovato
return result;
}
}