Cod sursa(job #1570659)

Utilizator alexandru92alexandru alexandru92 Data 16 ianuarie 2016 18:45:42
Problema Potrivirea sirurilor Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 1.9 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()>;

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

    for (size_t 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 x.second;
    }
    //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 x.second - j;
        }
    }
    return x.second;
    //}
}

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::min<int>(s.size() - p.size() + 1, NUM_OF_MAX_MATCHES_TO_SHOW));
    for (size_t i = p.size() - 1; 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 = 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;
}