Rezolvare completă PbInfo #2382 mesaje

După multe năzbâtii făcute împreună, Alex şi Cipri nu mai au voie să se întâlnească. Alex – strategul echipei – a plănuit o nouă poznă şi a decis să-i transmită prietenului său planul de luptă, constând din anumite cuvinte dintr-un mesaj m[0]. Pentru a nu fi descoperiți, i-a trimis ulterior mai multe mesaje m[1], m[2], … lui Cipri, acesta trebuind să le descifreze folosind convenția secretă stabilită la începutul prieteniei lor și să “acționeze”. Fiecare mesaj m[i] este format din mai multe cuvinte, separate prin câte un spațiu, numerotate cu valori consecutive, începând de la 1.
Pentru a afla planul, Cipri trebuie să găsească cea mai mare valoare i ≥ 0 astfel încât mesajele m[i] și m[0] să conțină cel puțin un cuvânt identic având același număr de ordine în ambele mesaje. Din m[0] se păstrează toate cuvintele care se găsesc și în mesajul m[i] cu același număr de ordine ca în m[0].
Cuvintele păstrate trebuie ordonate în ordine descrescătoare lexicografică a puterii lor. Puterea cuvântului cu numărul de ordine j în m[0] este egală cu șirul ordonat descrescător al indicilor mesajelor în care apare cu același număr de ordine ca în m[0]. Astfel, un cuvânt care a apărut cu numărul de ordine 2 în mesajele m[0], m[6] și m[8] are puterea {8,6,0}. Dacă două cuvinte au aceeași putere, vor rămâne în ordinea din mesajul inițial.
Lui Cipri nu i-a mai rămas decât să citească fiecare cuvânt de la dreapta la stânga şi a descifrat tot planul de luptă!

Cerința

Cunoscând mesajele transmise de Alex, ajutaţi-l pe Cipri să descifreze planul de luptă conform convenţiei secrete.

Date de intrare

Fișierul de intrare mesaje.in conține în ordine mesajele m[0], m[1], m[2], …, câte unul pe linie.

Date de ieșire

Fișierul de ieșire mesaje.out va conține pe prima linie numărul n de cuvinte ale planului de luptă, iar pe cea de a doua linie cele n cuvinte ale planului de luptă.

Restricții și precizări

  • Mesajele sunt memorate câte unul pe linie, fiind formate din cuvinte separate prin câte un spaţiu.
  • Lungimea unui cuvânt este de maximum 20 de caractere, litere mici ale alfabetului englez.
  • Lungimea unui mesaj este de maximum 30002 caractere.
  • Toate mesajele au acelaşi număr de cuvinte.
  • Fișierul de intrare conține cel puțin unul și cel mult 128 de mesaje.
  • Orice linie din fişierul de intrare (mesaj) se termină cu marcajul de sfârşit de linie (newline). Caracterul newline nu va fi considerat ca făcând parte din mesaj.
  • Nu există mesaje vide.

Exemplul 1:

mesaje.in

inosos yy ataeclud ni
a yy ataeclud ni
yy inosos ni yy
inosos bb ataeclud ni
acni in e enib

mesaje.out

3
dulceata in sosoni

Explicație

Mesajele m[0] și m[4] nu conțin cuvinte identice cu același număr de ordine. Mesajele m[0] și m[3] conțin trei cuvinte identice cu același număr de ordine: inosos, ataeclud, ni. În ordinea puterii, ele sunt: ataeclud {3,1,0}, ni {3,1,0}, inosos {3,0}.

Exemplul 2:

mesaje.in

miras ep maeg

mesaje.out

3
sarim pe geam

Explicație

Pentru că a primit un singur mesaj, planul de luptă conţine oglinditele cuvintele din textul iniţial având toate aceeaşi putere, citite de la dreapta la stânga.

Cum e corect?

cout < "As la info"; cout << "As la info"; cout >> "As la info";

Felicitări! Poți mai mult?

Avem sute de probleme pentru tine, fiecare cu explicații ușor de înțeles.

Greșit, dar nu-i bai!

Antrenează-te cu sutele de probleme pe care ți le-am pregătit. Îți explicăm fiecare problemă în parte.

Rezolvare

Iată rezolvarea de 100 de puncte pentru problema mesaje:

#include <bits/stdc++.h>
using namespace std;

#define NMAX 129
#define MAXCUV 15001
#define LMAX 30010

char linie[LMAX], l0[LMAX];
char *m0[MAXCUV], *mi[MAXCUV];
int o[MAXCUV], oaux[MAXCUV];
unsigned long long vset2[MAXCUV][2];
int i, j, l, q, better, K, M, N;

void msort(int li, int ls)
{
    int mid;

    if (li < ls)
    {
        mid = (li + ls) >> 1;
        msort(li, mid);
        msort(mid + 1, ls);

        i = li;
        j = mid + 1;
        l = li - 1;

        while (i <= mid && j <= ls)
        {
            better = 0;
            for (q = 0; q < 2; q++)
                if (vset2[o[i]][q] > vset2[o[j]][q])
                {
                    better = 1;
                    break;
                }
                else
                if (vset2[o[i]][q] < vset2[o[j]][q])
                {
                    better = - 1;
                    break;
                }

            l++;

            if (better >= 0)
            {
                oaux[l] = o[i];
                i++;
            }
            else
            {
                oaux[l] = o[j];
                j++;
            }
        }

        while (i <= mid)
        {
            l++;
            oaux[l] = o[i];
            i++;
        }

        while (j <= ls)
        {
            l++;
            oaux[l] = o[j];
            j++;
        }

        for (i = li; i <= ls; i++)
            o[i] = oaux[i];
    }
}

void solve(void)
{
    int i, j, L, imax = 0;

    freopen("mesaje.in", "r", stdin);

    for (j = 0; j < MAXCUV; j++)
        vset2[j][0] = vset2[j][1] = 0;

    for (i = 0; 1; i++)
    {
        memset(&linie, 0, sizeof(linie));
        fgets((char*)&linie, LMAX, stdin);

        L = strlen(linie);
        while (L > 0 && (linie[L] < 'a' || linie[L] > 'z'))
        {
            linie[L] = 0;
            L--;
        }

        if (L == 0)
        {
            M = i;
            break;
        }

        N = 1;
        for (j = 1; j < L; j++)
            if (linie[j] == ' ')
                N++;

        N = 1;
        mi[0] = &linie[0];

        for (j = 1; j < L; j++)
            if (linie[j] == ' ')
            {
                linie[j] = 0;
                mi[N] = &linie[j + 1];
                N++;
            }

        if (i == 0)
        {
            memcpy(l0, linie, L + 1);
            for (j = 0; j < N; j++)
                m0[j] = l0 + (mi[j] - linie);
        }
        else
        {
            for (j = 0; j < N; j++)
            {
                if (!strcmp(mi[j], m0[j]))
                {
                    imax = i;

                    if (i >= 64)
                        vset2[j][0] |= (1ULL << (i - 64));
                    else
                        vset2[j][1] |= (1ULL << i);
                }
            }
        }
    }

    if (imax == 0)
    {
        K = N;
        for (j = 0; j < N; j++)
            o[j] = j;
    }
    else
    {
        K = 0;
        for (j = 0; j < N; j++)
        {
            if ((imax >= 64 && (vset2[j][0] & (1ULL << (imax - 64)))) ||
                (imax < 64 && (vset2[j][1] & (1ULL << (imax)))))
            {
                o[K] = j;
                K++;
            }
        }
    }

    msort(0, K - 1);
}

void writeOutputData(void)
{
    freopen("mesaje.out", "w", stdout);

    printf("%d\n", K);
    for (i = 0; i < K; i++)
    {
        if (i > 0)
            printf(" ");

        for (j = strlen(m0[o[i]]) - 1; j >= 0; j--)
            printf("%c", m0[o[i]][j]);
    }

    printf("\n");
}

int main()
{
    int tstart = clock();
    solve();
    writeOutputData();

    return 0;
}

Atenție

Enunțurile afișate pe această pagină aparțin exclusiv site-ului PbInfo. Astfel, pentru ștergerea conținutului, puteți să ne contactați la adresa Adresa de email.

Rezolvarea problemei #2382 mesaje

Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #2382 mesaje de pe PbInfo.ro. Atenție: nu încurajăm copiatul codului! Totuși, credem cu tărie că analizarea unei soluții corecte este o metodă foarte ușoară de a învăța informatică, astfel că oferim sursele pentru peste 1500 de probleme de pe platforma PbInfo.ro.

Pentru rezolvări PbInfo de la peste 1500 de probleme, vă invităm să intrați pe site-ul nostru!