Cod sursa(job #1258914)

Utilizator gabrieligabrieli gabrieli Data 9 noiembrie 2014 15:56:43
Problema Potrivirea sirurilor Scor 14
Compilator cpp Status done
Runda Arhiva educationala Marime 1.96 kb
#include <cmath>
#include <cstdint>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

constexpr uint32_t M1 = 100007;
constexpr uint32_t M2 = 100021;
constexpr uint32_t B = 128;

inline uint32_t hashf(const string& text, const uint32_t base, const uint32_t m);

struct StringHash{
    uint32_t base;
    uint32_t base_pow_length;
    uint32_t m;
    size_t length;
    
    StringHash(uint32_t base, uint32_t m, uint32_t length) : base(base), m(m), length(length) {
        base_pow_length = pow(base, length);
    }
    
    uint32_t operator()(const string& text) const {
        uint32_t result = 0;
        for (char c : text)
            result = ((result * base) % m + c) % m;
        return result;
    }
    
    uint32_t rehash(uint32_t old_h, char c_significant, char c_new) const {
        return ((old_h * base) % m + m - (c_significant * base_pow_length) % m + c_new) % m;
    }
};

int main() {
    ifstream fin("strmatch.in");
    ofstream fout("strmatch.out");
    
    string query, text;
    fin >> query >> text;
    
    if (query.size() > text.size()) {
        fout << "0\n";
        return 0;
    }
    
    StringHash hash1(B, M1, query.size()), hash2(B, M2, query.size());
    
    size_t matches = 0;
    vector<size_t> positions;
    
    uint32_t HQ1 = hash1(query);
    uint32_t HQ2 = hash2(query);
    
    size_t i = 0;
    uint32_t h1 = hash1(text.substr(0, query.size()));
    uint32_t h2 = hash2(text.substr(0, query.size()));
    
    while (true) {
        if (h1 == HQ1 && h2 == HQ2) {
            matches++;
            if (matches <= 1000) positions.push_back(i);
        }
        
        if (i + query.size() < text.size()) {
            h1 = hash1.rehash(h1, text[i], text[i + query.size()]);
            h2 = hash2.rehash(h2, text[i], text[i + query.size()]);
            i++;
        }
        else break;
    }
     
    fout << matches << '\n';
    for (size_t p : positions) fout << p << ' ';
    fout << endl;
    
    return 0;
}