Cod sursa(job #3300323)

Utilizator stefan05Vasilache Stefan stefan05 Data 14 iunie 2025 19:33:25
Problema Potrivirea sirurilor Scor 14
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.11 kb
#include <fstream>
#include <cstring>

//Boyer-Moore

#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 < 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]
    // h[i] = cel mai mare sufix care e si prefix pentru pattern[i...m-1]

    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;
    }

    //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[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?"
    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;
            i = i + k - f[k];
            k = f[k];
        }
        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]];
                //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 = 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;
}