Cod sursa(job #2237890)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 3 septembrie 2018 19:43:37
Problema Potrivirea sirurilor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.55 kb
#include <bits/stdc++.h>

using namespace std;

// String Hasher
template <int B, int MOD>
struct Hasher {
    // Static array of powers of B
    static vector <int> pows;
    static void resize(int newSz) {
        if (newSz > pows.size()) {
            const int oldSz = pows.size();
            pows.resize(newSz);
            for (int i = oldSz; i < newSz; ++i)
                pows[i] = ((1LL * B * pows[i - 1]) % MOD);
        }
    }
    static int getPow(int pw) {
        while (pw >= (int)pows.size())
            resize(2 * pows.size());
        return pows[pw];
    }

    // Data members
    int h, sz;
    // Constructors
    Hasher(): h(0), sz(0) {}
    Hasher(int ch): h(ch), sz(1) {}
    Hasher(int _h, int _sz): h(_h), sz(_sz) {}

    // Pushes
    void push_back(int ch) { h = (1LL * h * B + ch) % MOD, ++sz; }
    void push_front(int ch) { h = (1LL * ch * getPow(sz) + h) % MOD, ++sz; }
    // Pops
    void pop_back(int ch) {
        --sz;
        h = (h - ch) % MOD;
        if (h < 0) h += MOD;
    }
    void pop_front(int ch) {
        --sz;
        h = (h - 1LL * getPow(sz) * ch) % MOD;
        if (h < 0) h += MOD;
    }
    // Concatenation
    friend Hasher operator+(const Hasher &a, const Hasher &b) { return Hasher((1LL * a.h * getPow(b.sz) + b.h) % MOD, a.sz + b.sz); }
    // Comparison
    friend bool operator==(const Hasher &a, const Hasher &b) { return make_pair(a.h, a.sz) == make_pair(b.h, b.sz); }
};
template <int B, int MOD>
vector <int> Hasher <B, MOD> :: pows = {1};

typedef Hasher <263, 1000000000 + 7> H1;
typedef Hasher <277, 1000000000 + 9> H2;

int main() {
    ifstream cin("strmatch.in");
    ofstream cout("strmatch.out");

    string pattern, str;
    cin >> pattern >> str;

    H1 :: resize(pattern.size());
    H2 :: resize(pattern.size());

    H1 h_pat1, h1;
    H2 h_pat2, h2;
    for (auto it: pattern) {
        h_pat1.push_back(it);
        h_pat2.push_back(it);
    }

    vector <int> ans;
    for (int i = 0; i < str.size(); ++ i) {
        h1.push_back(str[i]);
        h2.push_back(str[i]);
        if (i >= pattern.size() - 1) {
            if (h1 == h_pat1 && h2 == h_pat2)
                ans.push_back(i - pattern.size() + 1);
            h1.pop_front(str[i - pattern.size() + 1]);
            h2.pop_front(str[i - pattern.size() + 1]);
        }
    }

    cout << ans.size() << '\n';
    if (ans.size() > 1000)
        ans.resize(1000);
    for (int i = 0; i < ans.size(); ++ i)
        cout << ans[i] << " \n"[i + 1 == ans.size()];
    return 0;
}