Cod sursa(job #1874023)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 9 februarie 2017 16:56:31
Problema Potrivirea sirurilor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.27 kb
#include<iostream>
#include<fstream>
#include<cstring>
using namespace std;
ifstream f("strmatch.in");
ofstream g("strmatch.out");

// algoritmul Rabin-Karp

const int NMax = 2000000 + 3;
const int mod1 = 100007;
const int mod2 = 100021;
const int base = 73;
// base = baza pentru functia rolling hash Rabin fingerprint

int nrSol;
char a[NMax],b[NMax];
bool sol[NMax];

int main() {
    f.getline(a+1,NMax);
    f.getline(b+1,NMax);

    int nrA,nrB;
    nrA = strlen(a+1);
    nrB = strlen(b+1);
    if (nrA>nrB) {
        g<<0;
        return 0;
    }

    // se calculeaza valorea hash a primului sir modulo la doua numere prime intre ele.
    int hashA1=0,hashA2=0,pw1=1,pw2=1;
    for (int i=1;i<=nrA;++i) {
        hashA1 = (hashA1 * base + a[i]) % mod1;
        hashA2 = (hashA2 * base + a[i]) % mod2;

        if (i!=1) {
            pw1 = (pw1*base) % mod1;
            pw2 = (pw2*base) % mod2;
        }
    }
    // se calculeaza si valorea hash a primei subsecvente de lungime |A| din sirul B.
    int hashB1=0,hashB2=0;
    for (int i=1;i<=nrA;++i) {
        hashB1 = (hashB1 * base + b[i]) % mod1;
        hashB2 = (hashB2 * base + b[i]) % mod2;
    }

    // daca cele doua valori hash sunt congruente modulo la cele doua numere,
    // atunci sansa ca ele sa nu fie acelasi sir este foarte mica.
    // O valoare hash care da rezultatele respective prin operatia modulo
    // se gaseste o data la fiecare mod1 * mod2 valori (mod1,mod2 fiind prime intre ele)
    if (hashA1 == hashB1 && hashA2 == hashB2) {
        ++nrSol;
        sol[1]=true;
    }

    // valorea hash a urmatoarei subsecvente din B se va calcula din valoarea precedenta
    for (int i=nrA+1;i<=nrB;++i) {
        //hashB1 =  (hashB1 - b[i-nrA]*pw1) * base + b[i];
        hashB1 = ((hashB1 - (b[i-nrA]*pw1)%mod1 + mod1) * base + b[i]) % mod1;
        hashB2 = ((hashB2 - (b[i-nrA]*pw2)%mod2 + mod2) * base + b[i]) % mod2;

        if (hashA1 == hashB1 && hashA2 == hashB2) {
            sol[i-nrA+1]=true;
            ++nrSol;
        }
    }
    g<<nrSol<<'\n';
    nrSol=0;
    for (int i=1;i<=nrB-nrA+1 && nrSol<1000;++i) {
        if (sol[i]) {
            g<<i-1<<' ';
            ++nrSol;
        }
    }
    f.close();g.close();
    return 0;
}