Pagini recente » Profil avenger | Profil Nicolaalexandra | Statistici Ivan Vlad (Vladinho96) | telefon3 | Cod sursa (job #3300540)
#include <fstream>
#include <cstring>
#define SMAX 2000005
#define ALFMAX 26
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] - 'A'] = 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
int st, dr;
for (st = 0, dr = m; st < dr; ++st, --dr)
swap(h[st], h[dr]);
//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
gs[m] = m - 1;
for (i = 0; i < m; ++i)
{
int lg = h[i];
//pentru sufixul lui pattern cu lungime lg, care incepe la pozitia m-lg, l-am gasit pe pozitia i
if (lg >= 0 && m-lg >= 0)
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)
{
rez[++nr] = i;
int shiftbc = max(1, m - (k + 1) - bc[s[i + m - 1 - k] - 'A']);
int shiftgs = max(1, m - k - gs[m - k]);
i += max(shiftbc, shiftgs);
k = 0;
}
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 = m - (k + 1) - bc[s[i + m - 1 - k] - 'A'];
//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;
}