Cod sursa(job #2237911)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 3 septembrie 2018 22:18:23
Problema Potrivirea sirurilor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.83 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 > (int)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;
    }
    // Push-pop
    void push_back_pop_front(int pushCh, int popCh) {
        h = ((h - 1LL * getPow(sz - 1) * popCh) * B + pushCh) % 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() + 1);
    //H2 :: resize(pattern.size() + 1);

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

    for (int i = 0; i < pattern.size(); ++ i) {
        h1.push_back(str[i]);
        //h2.push_back(str[i]);
    }

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

    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;
}