Cod sursa(job #1570643)

Utilizator alexandru92alexandru alexandru92 Data 16 ianuarie 2016 18:18:55
Problema Potrivirea sirurilor Scor 14
Compilator cpp Status done
Runda Arhiva educationala Marime 2.81 kb
#include <fstream>
#include <array>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <limits>

using std::string;
using std::vector;
using std::pair;
using std::array;

const int NMAX = 2000011;
const int NUM_OF_MAX_MATCHES_TO_SHOW = 1000;

using BadCharTable = array<vector<int>, std::numeric_limits<char>::max()>;

vector<int> ZAlgo(const string& p) {
    vector<int> Z(p.size(), 0);

    Z[0] = p.size();
    for (int k = 1, lt  = 0, rt = 0; k < p.size(); ++k) {
        if (k > rt) {
            int i;
            for (i = 0; i + k < p.size() && p[i] == p[i + k]; ++i);
            Z[k] = i;

            if (i) {
                lt = k;
                rt = i + k - 1;
            }
        }
        else {
            if (Z[k - lt] < rt - k + 1) {
                Z[k] = Z[k - lt];
            }
            else {
                int i;
                for (i = rt + 1; i < p.size() && p[i] == p[i - k]; ++i);
                Z[k] = i - k;
                lt = k;
                rt = i - 1;
            }
        }
    }

    return Z;
}


BadCharTable buildBadCharTable(const string& p) {
    BadCharTable t;

    for (int i = 0; i < p.size(); ++i) {
        t[p[i]].push_back(i);
    }

    return t;
}

int computeBadCharShift(const pair<char, int>& x, const BadCharTable& t) {
    if (t[x.first].empty()) {
        return 0;
    }
    else if (t[x.first].size() <= 15) {
        for (int i = t[x.first].size() - 1; i >= 0; --i) {
            int j = t[x.first][i];
            if (j < x.second) {
                return j + 1;
            }
        }
        return 0;
    }
    else {
        const auto& it = std::lower_bound(t[x.first].begin(), t[x.first].end(), x.second);
        return it == t[x.first].end() || it == t[x.first].begin() ? 0 : *(it - 1) + 1;
    }
}

pair<int, vector<int>> strMatch(const string& p, const  string& s) {
    BadCharTable badCharTable = buildBadCharTable(p);

    int numMatches = 0, skip = 0;
    vector<int> matches;

    matches.reserve(std::max<int>(s.size() - p.size() + 1, NUM_OF_MAX_MATCHES_TO_SHOW));
    for (int i = p.size(); i < s.size(); i += skip) {
        int k = i, j = p.size() - 1;
        for (; j >= 0 && s[k] == p[j]; --k, --j);

        if (j < 0) {
            skip = 1;
            ++numMatches;
            if (numMatches < matches.capacity()) {
                matches.push_back(k + 1);
            }
        }
        else {
            skip = p.size() - computeBadCharShift({s[i], j}, badCharTable);
        }
    }

    return std::make_pair(numMatches, matches);
}


int main() {
    string p, s;
    std::ifstream in{"strmatch.in"};
    std::ofstream out{"strmatch.out"};

    in >> p >> s;
    const auto x = strMatch(p, s);
    out << x.first << '\n';
    std::copy(x.second.begin(), x.second.end(), std::ostream_iterator<int>{out, " "});

    return 0;
}