infoarena

infoarena - concursuri, probleme, evaluator, articole => FMI No Stress 2012 => Subiect creat de: Serban Andrei Stan din Mai 11, 2012, 14:06:05



Titlul: Potrivire
Scris de: Serban Andrei Stan din Mai 11, 2012, 14:06:05
Aici puteti discuta despre problema potrivire (http://infoarena.ro/problema/potrivire)


Titlul: Răspuns: Potrivire
Scris de: cristescu liviu din Mai 11, 2012, 15:16:40
se poate sa existe litere mari in sirul A?


Titlul: Răspuns: Potrivire
Scris de: Ilie Andrei din Mai 11, 2012, 15:32:42
Se poate sa nu existe solutie?


Titlul: Potrivire
Scris de: Oncescu Costin din Mai 11, 2012, 15:34:16
In exemplu raspunsul e pentru subsir dar in fisierul de iesire scrie subsecventa.b trebuie sa fie subsecventa sau subsir al sirului dat?


Titlul: Răspuns: Potrivire
Scris de: Andrei Grigorean din Mai 11, 2012, 15:55:38
Se poate sa nu existe solutie?

+


Titlul: Potrivire
Scris de: Oncescu Costin din Mai 11, 2012, 15:56:10
Sper ca ati observat ca s-a blocat evaluatorul la aceasta problema.


Titlul: Răspuns: Potrivire
Scris de: Simoiu Robert din Mai 11, 2012, 15:59:19
S-a blocat de tot :P.


Titlul: Răspuns: Potrivire
Scris de: Florian Marcu din Mai 11, 2012, 16:11:51
In cazul in care nu exista solutie, se afiseaza -1.


Titlul: Răspuns: Potrivire
Scris de: Andrei Grigorean din Mai 11, 2012, 16:12:13
In cazul in care nu exista solutie, se afiseaza -1.

Sa modificati enuntul.


Titlul: Răspuns: Potrivire
Scris de: MciprianM din Mai 11, 2012, 17:03:17
Citat
acceptam solutii barbare

Cat de barbare?


Titlul: Răspuns: Potrivire
Scris de: Radu-Andrei Szasz din Mai 11, 2012, 17:43:07
* din sirul B poate fi inlocuita cu o subsecventa care apartine neaparat sirului B, sau poate apartine si sirului A?


Titlul: Răspuns: Potrivire
Scris de: Visan Radu din Mai 11, 2012, 19:23:02
De ce nu mai apare rezultatul evaluarii la problema asta?
La celelalte vad ca apare borderoul de evaluare.


Titlul: Răspuns: Potrivire
Scris de: Mircea Dima din Mai 11, 2012, 22:08:26
Cred ca mergea in O(n + m) cu Aho Corasik... Era mai interesant daca erau limitele mai mari :)


Titlul: Răspuns: Potrivire
Scris de: George Marcus din Mai 11, 2012, 22:19:52
Eu am facut KMP.


Titlul: Răspuns: Potrivire
Scris de: Mircea Dima din Mai 11, 2012, 22:23:12
Un singur KMP ? sau vreo 30?


Titlul: Răspuns: Potrivire
Scris de: Tudor Tiplea din Mai 11, 2012, 22:32:04
Eu am facut 30 KMP.


Titlul: Răspuns: Potrivire
Scris de: George Marcus din Mai 11, 2012, 22:36:16
Nu conteaza cate sunt, pana la urma tot O(N + M) iese.


Titlul: Răspuns: Potrivire
Scris de: Mircea Dima din Mai 11, 2012, 22:52:30
Esti sigur?  Eu cred ca iese O(30 * O(n + m)),
iar 30 nu e constanta... e numarul de *


Titlul: Răspuns: Potrivire
Scris de: Andrei Grigorean din Mai 11, 2012, 22:59:47
Esti sigur?  Eu cred ca iese O(30 * O(n + m)),
iar 30 nu e constanta... e numarul de *

Merge in O(N + M) cu KMP indiferent de numarul de stelute.


Titlul: Răspuns: Potrivire
Scris de: Buleandra Cristian din Mai 11, 2012, 23:13:03
Merge si brut, fara niciun fel de optimizare (chiar mai repede decat KMP din ce am vazut)
http://infoarena.ro/job_detail/747839


Titlul: Răspuns: Potrivire
Scris de: George Marcus din Mai 11, 2012, 23:19:05
Esti sigur?  Eu cred ca iese O(30 * O(n + m)),
iar 30 nu e constanta... e numarul de *
Ne incurcam in simboluri :D
Cele 30 de KMP-uri nu se fac pe toata lungimea sirului, ci doar pe portiunile dintre stelute. De aceea, per total, e ca si cum ai face o singura data pe tot sirul.


Titlul: Răspuns: Potrivire
Scris de: Cristian Lambru din Mai 11, 2012, 23:56:09
Ne incurcam in simboluri :D
Cele 30 de KMP-uri nu se fac pe toata lungimea sirului, ci doar pe portiunile dintre stelute. De aceea, per total, e ca si cum ai face o singura data pe tot sirul.

Nu exact. Intradevar, pana la urma M-ul, in cazul nostru lungimea fiecarei secvente delimitate de doua stelute este in total lungimea lui B, dar KMP-ul se repeta de fiecare data cand se gaseste o noua astfel de secventa . La dimensiuni imense ale sirului si la un numar mai mare de stelute, complexitatea O(nr_stelute * (M + N)) este diferita in practica fata de O(M+N).


Titlul: Răspuns: Potrivire
Scris de: Mircea Dima din Mai 11, 2012, 23:57:08
Atunci eu faceam KMP de 30 de ori... calculam prefixul pt fiecare portiune dintre stelute si apoi mergeam de 30 de ori pe primul sir.
Deci la mine chiar e O(30 * (N + M)). Daca voi faceti altfel...


Titlul: Răspuns: Potrivire
Scris de: Mircea Dima din Mai 11, 2012, 23:59:32
Esti sigur?  Eu cred ca iese O(30 * O(n + m)),
iar 30 nu e constanta... e numarul de *

Merge in O(N + M) cu KMP indiferent de numarul de stelute.


Wef, tu ai bagat un singur KMP ? sigur ai O(N + M) ? Eu cred ca O(N + M) merge doar cand bagi Aho Corasik
peste sirurile dintre stelute...


Titlul: Răspuns: Potrivire
Scris de: Adrian Budau din Mai 12, 2012, 02:18:18
Merge si un singur KMP in care consideri ca * se potriveste cu orice. La functia prefix(si implicit si la KMP) te intorci pana la ultima steluta potrivita cand nu e bun caracterul curent.


Titlul: Răspuns: Potrivire
Scris de: Andrei Grigorean din Mai 12, 2012, 10:43:00
Iata sursa mea care are complexitate O(N + M):

Cod:
#include <fstream>
#include <string>
#include <vector>
using namespace std;

#define FORIT(it, v) for (typeof((v).begin()) it = (v).begin(); it != (v).end(); ++it)

ifstream fin("potrivire.in");
ofstream fout("potrivire.out");

const int MAX_N = 10005;

int n, m;
string text, pattern;
int prefix[MAX_N];

vector<string> tokenize(string &s) {
    vector<string> tokens;
    string token;

    FORIT(it, s)
        if (*it == '*') {
            if (!token.empty())
                tokens.push_back(token);
            token.clear();
        } else {
            token += *it;
        }
    if (!token.empty())
        tokens.push_back(token);

    return tokens;
}

void find_prefix(string &pattern) {
    m = pattern.size();

    int p = 0;
    prefix[1] = 0;

    for (int i = 2; i <= m; ++i) {
        while (p && pattern[p] != pattern[i - 1])
            p = prefix[p];
        if (pattern[p] == pattern[i - 1])
            ++p;
        prefix[i] = p;
    }
}

int main() {
    fin >> n >> m;
    fin >> text >> pattern;

    vector<string> tokens = tokenize(pattern);
   
    int idx = 0, left = -1, right = -1;
    for (size_t i = 0; i < tokens.size(); ++i) {
        find_prefix(tokens[i]);

        int p = 0;
        while (p != m) {
            if (idx == n) {
                fout << "-1\n";
                return 0;
            }

            while (p && tokens[i][p] != text[idx])
                p = prefix[p];
            if (tokens[i][p] == text[idx])
                ++p;
            ++idx;
        }

        if (i == 0) left = idx - m + 1;
        if (i + 1 == tokens.size()) right = idx;
    }

    fout << left << " " << right << "\n";
}


Titlul: Răspuns: Potrivire
Scris de: George Marcus din Mai 12, 2012, 13:23:31
Ma lamureste cineva si pe mine care e faza cu O(30 * (N + M))? Nu inteleg care este logica. Parcurg o singura data atat A-ul cat si B-ul. In sursa lui wefgef, de exemplu, find_prefix parcurge o portiune dintre stelute (deci per total M), iar idx parcurge sirul A (deci per total N).


Titlul: Răspuns: Potrivire
Scris de: Cristian Lambru din Mai 12, 2012, 13:37:06
Depinde cum ai facut.

Din cate am inteles eu (sper sa nu ma insel), tu ai luat fiecare secventa ce se afla intre doua stelute si ai calculat cu KMP aparitiile acestei secvente in sirul A. Pentru fiecare secventa (numar de stelute + 1) faci KMP, ceea ce rezulta o complexitate O(Nr_stelute) * O(N+M) (a doua parte provine de la KMP).

Daca ai facut ca wefgef, atunci ai intradevar O(N+M), dar fara impartirea lui B in nr_stelute secvente.


Titlul: Răspuns: Potrivire
Scris de: George Marcus din Mai 12, 2012, 13:48:21
Am facut ca si wefgef, incepand cautarea in A dupa ultima pozitie gasita anterior. Mi se parea si mai complicat de implementat daca era sa caut de fiecare data in tot sirul A.


Titlul: Răspuns: Potrivire
Scris de: Cristian Lambru din Mai 12, 2012, 13:55:02
Aici ai dreptate, solutia pe care am spus-o eu mi-a mancat zilele in timpul concursului, fiind necesar un cod de vreo 3 ori mai lung si cu ceva mai multe buguri posibile, dar in lipsa de altceva si cu o mica criza de timp s-a comportat mai mult decat decent :) .