Cod sursa(job #1399551)

Utilizator alexandru70Ungurianu Alexandru alexandru70 Data 24 martie 2015 20:03:37
Problema Potrivirea sirurilor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.14 kb
#include <fstream>
#include <vector>
#include <iostream>

using namespace std;

typedef long long BigUnsigned;

namespace Consts {
	const BigUnsigned mod = 666013;
	const BigUnsigned p1 = 307;
	const BigUnsigned p2 = 577;
	BigUnsigned p1_n;
	BigUnsigned p2_n;
};

BigUnsigned fast_pow(BigUnsigned b, BigUnsigned e) {
	if(e == 0) return 1;
	if(e == 1) return b%Consts::mod;

	if(e%2 == 0) {
		return fast_pow((b*b)%Consts::mod,e/2)%Consts::mod;
	}
	else {
		return (b*fast_pow((b*b)%Consts::mod,e/2))%Consts::mod;
	}
}

BigUnsigned step_hash1(BigUnsigned init_hash, char to_add, char to_remove) {
	return ((Consts::p1 * (init_hash + Consts::mod - (Consts::p1_n*to_remove)%Consts::mod))%Consts::mod + to_add)%Consts::mod;
}

BigUnsigned step_hash2(BigUnsigned init_hash, char to_add, char to_remove) {
	return ((Consts::p2 * (init_hash + Consts::mod - (Consts::p2_n*to_remove)%Consts::mod))%Consts::mod + to_add)%Consts::mod;
}

int main() {
	ifstream in("strmatch.in");
	string small,big;
	in >> small >> big;

	ofstream out("strmatch.out");
	if(small.size() > big.size()) {
		out << "0\n";
		return 0;
	}

	Consts::p1_n = fast_pow(Consts::p1,small.size()-1);
	Consts::p2_n = fast_pow(Consts::p2,small.size()-1);

	BigUnsigned small_hash1=0,small_hash2=0;

	for(char c:small) {
		small_hash1 = step_hash1(small_hash1,c,0);
		small_hash2 = step_hash2(small_hash2,c,0);
	}

	vector<unsigned> solutions;

	BigUnsigned big_hash1=0,big_hash2 = 0;
	for(unsigned i = 0; i < small.size(); ++i) {
		big_hash1 = step_hash1(big_hash1,big[i],0);
		big_hash2 = step_hash2(big_hash2,big[i],0);
	}

	unsigned count = 0;
	if(big_hash1 == small_hash1 && big_hash2 == small_hash2) {
		solutions.push_back(0);
		count++;
	}
	for(unsigned i = 0; i < big.size() - small.size(); ++i) {
		big_hash1 = step_hash1(big_hash1,big[i+small.size()],big[i]);
		big_hash2 = step_hash2(big_hash2,big[i+small.size()],big[i]);
		//cout << small_hash << ' ' << big_hash << '\n';
		if(big_hash1 == small_hash1 && big_hash2 == small_hash2) {
			if(solutions.size() < 1000) {
				solutions.push_back(i+1);
			}
			count ++;
		}
	}

	out << count << '\n';
	for(unsigned s:solutions) {
		out << s << ' ';
	}
	out << '\n';

	return 0;
}