Cod sursa(job #2725942)

Utilizator preda.andreiPreda Andrei preda.andrei Data 19 martie 2021 21:40:12
Problema Potrivirea sirurilor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.25 kb
#include <cstdint>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

class Result {
public:
    void AddMatch(int pos);

    friend ostream& operator<<(ostream& os, const Result& res);

private:
    vector<int> matches_;
    int match_count_ = 0;
};

void Result::AddMatch(int pos) {
    if (matches_.size() < 1000) {
        matches_.push_back(pos);
    }
    match_count_ += 1;
}

ostream& operator<<(ostream& os, const Result& res) {
    os << res.match_count_ << "\n";
    for (const auto& pos : res.matches_) {
        os << pos << " ";
    }
    os << "\n";
    return os;
}

constexpr int64_t kBase = 73;
constexpr int64_t kMod1 = 100007;
constexpr int64_t kMod2 = 100021;

int64_t Power(int64_t base, int64_t exp, int64_t mod) {
    int64_t res = 1;
    for (int64_t i = 1; i <= exp; i += 1) {
        res = (res * base) % mod;
    }
    return res;
}

int64_t Advance(int64_t hash, char ch, int64_t mod) {
    return (hash * kBase % mod + ch) % mod;
}

int64_t Hash(const string& str, int64_t mod) {
    int64_t hash = 0;
    for (const auto& ch : str) {
        hash = Advance(hash, ch, mod);
    }
    return hash;
}

Result Solve(const string& needle, const string& haystack) {
    int64_t needle_hash1 = Hash(needle, kMod1);
    int64_t needle_hash2 = Hash(needle, kMod2);

    int64_t pow1 = Power(kBase, needle.size() - 1, kMod1);
    int64_t pow2 = Power(kBase, needle.size() - 1, kMod2);

    int n = needle.size();
    int64_t hash1 = Hash(haystack.substr(0, n - 1), kMod1);
    int64_t hash2 = Hash(haystack.substr(0, n - 1), kMod2);

    Result res;
    for (size_t i = n - 1; i < haystack.size(); i += 1) {
        hash1 = Advance(hash1, haystack[i], kMod1);
        hash2 = Advance(hash2, haystack[i], kMod2);

        auto l = i + 1 - n;
        if (hash1 == needle_hash1 && hash2 == needle_hash2) {
            res.AddMatch(l);
        }

        hash1 = (hash1 - pow1 * haystack[l] % kMod1 + kMod1) % kMod1;
        hash2 = (hash2 - pow2 * haystack[l] % kMod2 + kMod2) % kMod2;
    }
    return res;
}

int main() {
    ifstream fin("strmatch.in");
    ofstream fout("strmatch.out");

    string needle, haystack;
    getline(fin, needle);
    getline(fin, haystack);

    auto res = Solve(needle, haystack);
    fout << res << "\n";

    return 0;
}