Submission #1313057

#TimeUsernameProblemLanguageResultExecution timeMemory
1313057davidcNecklace (Subtask 4) (BOI19_necklace4)C++20
15 / 15
617 ms2700 KiB
#include <bits/stdc++.h>
#define all(a) (a).begin(), (a).end()
using namespace std;

typedef unsigned short u16;

struct Respuesta{
    int largo = 0;
    int inicioS = 0;
    int inicioT = 0;
};

void invertir_string(string &x){
    reverse(all(x));
}

Respuesta resolver_orientacion(const string &S, const string &T){
    int n = (int)S.size();
    int m = (int)T.size();


    string Sr = S, Tr = T;
     reverse(all(Sr));
     reverse(all(Tr));


    const int BLOQUE = 380;

    Respuesta mejor;


    vector<u16> dp(m + 1, 0), ndp(m + 1, 0);
    vector<u16> dp2(m + 1, 0), ndp2(m + 1, 0);


    vector<u16> filaLSP(m + 1, 0);


    for(int a0 = 0; a0 <= n; a0 += BLOQUE){
        int a1 = min(n + 1, a0 + BLOQUE);
        int filas = a1 - a0;

        vector<u16> almacen((size_t)filas * (m + 1), 0);

        auto ptr_fila = [&](int idx)->u16*{
            return &almacen[(size_t)idx * (m + 1)];
        };


        fill(all(dp), 0);
        fill(all(ndp), 0);


        for(int a = 1; a <= n; a++){
            ndp[0] = 0;
            for(int b = 1; b <= m; b++){
                if(Sr[a - 1] == Tr[b - 1]) ndp[b] = (u16)(dp[b - 1] + 1);
                else ndp[b] = 0;
            }
            dp.swap(ndp);

            if(a0 <= a && a < a1){

                fill(all(filaLSP), 0);

                for(int b = 1; b <= m; b++){
                    u16 l = dp[b];
                    if(l){
                        int inicio = b - (int)l;
                        if(filaLSP[inicio] < l) filaLSP[inicio] = l;
                    }
                }

                for(int j = 1; j <= m; j++){
                    u16 dec = (filaLSP[j - 1] ? (u16)(filaLSP[j - 1] - 1) : 0);
                    if(filaLSP[j] < dec) filaLSP[j] = dec;
                }

                u16 *dest = ptr_fila(a - a0);
                memcpy(dest, filaLSP.data(), (m + 1) * sizeof(u16));
            }
        }


        int i_min = n - (a1 - 1);
        int i_max = n - a0;
        i_min = max(i_min, 0);
        i_max = min(i_max, n);

        fill(all(dp2), 0);
        fill(all(ndp2), 0);

        for(int i = 0; i <= n; i++){
            if(i == 0){
                fill(all(filaLSP), 0);
            }else{
                ndp2[0] = 0;
                for(int j = 1; j <= m; j++){
                    if(S[i - 1] == T[j - 1]) ndp2[j] = (u16)(dp2[j - 1] + 1);
                    else ndp2[j] = 0;
                }
                dp2.swap(ndp2);

                fill(all(filaLSP), 0);
                for(int j = 1; j <= m; j++){
                    u16 l = dp2[j];
                    if(l){
                        int inicio = j - (int)l;
                        if(filaLSP[inicio] < l) filaLSP[inicio] = l;
                    }
                }
                for(int j = 1; j <= m; j++){
                    u16 dec = (filaLSP[j - 1] ? (u16)(filaLSP[j - 1] - 1) : 0);
                    if(filaLSP[j] < dec) filaLSP[j] = dec;
                }
            }

            if(i < i_min || i > i_max) continue;

            int a = n - i;
            int idx = a - a0;
            u16 *filaRev = ptr_fila(idx);


            for(int j = 0; j <= m; j++){
                int la = (int)filaLSP[j];
                int lb = (int)filaRev[m - j];
                int L = la + lb;

                if(L > mejor.largo){
                    mejor.largo = L;
                    mejor.inicioS = i - la;
                    mejor.inicioT = j - lb;
                }
            }
        }
    }

    return mejor;
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    string S, T;
    cin >> S >> T;
    int m = (int)T.size();


    Respuesta r1 = resolver_orientacion(S, T);


    string Trev = T;
    reverse(all(Trev));
    Respuesta r2 = resolver_orientacion(S, Trev);


    int inicioT_mapeado = m - (r2.inicioT + r2.largo);


    Respuesta mejor = r1;
    int mejorInicioT = r1.inicioT;

    if(r2.largo > mejor.largo){
        mejor = r2;
        mejorInicioT = inicioT_mapeado;
    }

    cout << mejor.largo << "\n";
    cout << mejor.inicioS << " " << mejorInicioT << "\n";

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...