-
Notifications
You must be signed in to change notification settings - Fork 0
/
zeta.h
164 lines (113 loc) · 3.55 KB
/
zeta.h
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
void zeta(string S, int Z[]);
void zeta(string S, int Z[]){
int n = S.length();
//Inizializzo Z
int i;
for ( i = 0; i <= n-1; i++) Z[i]=0;
//Lo Z blocco più a destra incontrato sin ora
int l=0;
int r=0;
for (i=1; i <= n-1; i++){
#ifdef DEBUG
cout << endl << "posizione i = " << i << endl;
cout << " z blocco = [" << l << ", " << r << "]" << endl;
#endif
//int eccedendo=0;
if(i<=r){//Caso in cui i e' dentro nell'ultimo z blocco
#ifdef DEBUG
cout<< " i e' dentro lo z blocco ..." << endl;
cout << " Lo z blocco e' lungo r ="<< r << " meno l = " << l <<" +1 cioe' : " << r-l+1 << endl;
#endif
//Qui discrimino i 3 casi (beta sottostringa dello z blocco alpha, beta suffisso dello z blocco e beta che sfora lo zeta blocco)->
int k = i-l;
#ifdef DEBUG
cout << "i cade nel prefisso del testo in posizione k = " << k << endl;
#endif
if (k+Z[k]/*-1*/ /*in Z[k] conto anche il carattere T[k] quindi -1*/<r-l+1 /*l e r sono entrambi dentro lo z blocco quindi sottraendoli mangio un carattere quindi +1*/
)
// La lunghezza di aplha e' r-l+1
{
if(i+Z[k]< S.length()){
#ifdef DEBUG
cout << "Copio il valore di Z dalla posizione k = "<< k << " alla posizione i = " << i << endl;
#endif
Z[i]=Z[k];
}else{
#ifdef DEBUG
cout << "Starei eccedendo..."<< endl;
cout << "Copio il valore di Z dalla posizione k = "<< k << " alla posizione i = " << i << endl;
#endif
Z[i]= S.length()-i;
}
#ifdef DEBUG
cout << "Questo era il caso contenuto strettamente , valore finale di Z[i]="<< Z[i] << endl;
#endif
}
if (k+Z[k]/*-1*/ ==r-l+1)
{
Z[i]= r-i+1;
#ifdef DEBUG
cout << "Meglio procedere con i confronti...";
cout << "Li ricomincio fra r+1 = "<< r+1<< "e r-l+1 =" << r-l+1 << endl;
#endif
int start1 = r+1; //r+1;
int start2 = r-i+1; //la lunghezza di gamma ;
int jj=0;
while(S[start1+jj] == S[start2+jj] && start1+jj < S.length()) {
Z[i]++;
jj++;
}
if(jj>0){
l=i;
r=i+Z[i]-1;
#ifdef DEBUG
cout << "Aggiorno lo Z blocco"<< endl;
#endif
}
#ifdef DEBUG
cout << "Questo era il caso gamma suffisso alpha, valore finale di Z[i]="<< Z[i] << endl;
#endif
}
if (k+Z[k]>r-l+1 ){
#ifdef DEBUG
cout << "k + Z[k] eccede lo z blocco ... "<< k + Z[k] <<" > "<< r-l+1 << endl;
#endif
Z[i]=r-i+1; // la lunghezza di gamma. Ricorda, considero sempre interni gli indici che delimitano una stringa.
/*Si noti che ora k+Z[i] vale esattamente la lunghezza di alpha cioe' i -l + r -i + 1 */
int start1 = r+1;
int start2 = r-l +1;
int jj=0;
#ifdef DEBUG
cout << "Sarebbe meglio procedere con i confronti...";
cout << "Li ricomincio fra k+1 = "<< k+Z[k]+1<< "e i+Z[i]+1 =" << i+Z[i]+1 << endl;
#endif
while(S[start1+jj] == S[start2+jj] && start1+jj < S.length()) {
Z[i]++;
jj++;
}
if(jj>0){
l=i;
r=i+Z[i]-1;
#ifdef DEBUG
cout << "Aggiorno lo Z blocco"<< endl;
#endif
}
}
}else{// caso in cui i e' oltre lo z blocco (continuo i confronti regolarmente)
#ifdef DEBUG
cout << "i e' fuori lo z blocco ..." << endl;
#endif
int j=0;
while(S[i+j]==S[j]) j++;
if(j>0){
//se siamo andati almeno un passo avanti:
#ifdef DEBUG
cout << "siamo andati avanti con i confronti per j =" << j << " posizioni." << endl;
#endif
Z[i]+=j;
r=i+Z[i]-1;
l=i;
}
}
}
}