Pagini recente » Rating Mateiu Ianis Cristian Vasile (KRISTY06) | Cod sursa (job #2630569) | Rating Alupoaie Darius (Darius_JK) | Cod sursa (job #45) | Cod sursa (job #3300549)
#include <fstream>
#include <cstring>
#define SMAX 2000005
#define ALFMAX 100
using namespace std;
ifstream fin("strmatch.in");
ofstream fout("strmatch.out");
char pattern[SMAX];
char s[SMAX];
int bc[ALFMAX], gs[SMAX];
int f[SMAX], h[SMAX];
int rez[SMAX]; int nr;
int k, i;
int main()
{
fin >> pattern >> s;
int m = strlen(pattern);
int n = strlen(s);
///PRECALCULARI
///bc[i] = ultima aparitie in pattern a caracterului char(i+'a')
for (i = 0; i < 26; ++i)
bc[i] = -1;
for (i = 0; i < m; ++i)
bc[pattern[i] - '0'] = i;
///gs[i] = ultima aparitie in pattern a sufixului pattern[i..m-1]
//f[i] = cel mai mare sufix care e si prefix pentru pattern[0...i-1] (primele i)
// h[i] = cel mai mare sufix care e si prefix pentru pattern[i...m-1]
// cum se afla h: aflam f pentru pattern inversat, inversam asta
f[0] = h[0] = -1;
for (i = 1; i <= m; ++i)
{
int k;
k = f[i - 1];
while (k >= 0 && pattern[k] != pattern[i - 1]) //din kmp
k = f[k];
if (k == -1)
f[i] = 0;
else
f[i] = k + 1;
//indici inversati
k = h[i - 1];
while (k >= 0 && pattern[m - 1 - k] != pattern[m - 1 - (i - 1)]) //din kmp
k = h[k];
if (k == -1)
h[i] = 0;
else
h[i] = k + 1;
}
//inverseaza h
//pentru pozitiile negative
for (i = 0; i <= m; ++i)
gs[i] = f[m] - (m - i);
//vrem sufix-prefix de lungime i, avem doar f[m]
//pentru pozitiile pozitive
for (i = 0; i <= m; ++i)
{
int lg = h[m-i];
//pentru sufixul lui pattern cu lungime lg, care incepe la pozitia m-lg, l-am gasit pe pozitia i
gs[m - lg] = i;
}
///REZOLVARE
//k = deplasament = lungimea bucatii corecta din dreapta
//i = pozitia pentru care testam: "apare pattern la pozitia i?"
i = 0; k = 0;
while (i <= n - m) //daca k == m, am gasit pattern
//daca i == n-m, suntem la sfarsit cu pattern-ul
{
if (k == m)
{
if (nr <= 1000) rez[++nr] = i;
else
nr++;
i += m - f[m]; k = f[m];
continue;
}
if (s[i + m - 1 - k] == pattern[m - 1 - k])
k++;
//al k-lea caracter (caracterul curent) de la dr la st e corect
else
{
//shift = cu cat trebuie sa mutam pattern
//shift = max(shiftbc, shiftgs), mut maxim posibil fara sa pierd cazuri
//s[i+m-1-k] este primul caracter gresit
int shiftbc = max(1, m - (k + 1) - bc[s[i + m - 1 - k] - '0']);
//m-(k+1) este pozitia fix dinainte de ultimele k elemente, care sunt corecte
//trebuie sa ajungem de la m-(k+1) la bc[s[i + m - 1 - k]], facem shiftbc pasi
int shiftgs = max(1, m - k - gs[m - k]);
//la poz m-k incep cele k elemente corecte gasite pana acum
//trebuie sa ajungem de la m-k la gs[m-k], facem shiftgs pasi
i += max(shiftbc, shiftgs);
k = 0;
}
}
fout << nr << '\n';
for (i = 1; i <= min(nr, 1000); ++i)
fout << rez[i] << ' ';
fout << '\n';
return 0;
}