Cod sursa(job #149335)

Utilizator scvalexAlexandru Scvortov scvalex Data 5 martie 2008 16:41:36
Problema Potrivirea sirurilor Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 2.98 kb
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <fstream>

using namespace std;

const int Factor = 73;
const int Mod1 = 100007;
const int Mod2 = 100021;

char P[2000002],
	 T[2000002];

int matched[1001],
	mn(0);

int M,
	N;

FILE *fout;

void rkmatch() {
	int ps1(0),
		ps2(0);
	for (int i(0); i < M; ++i) {
		ps1 = (ps1 * Factor + P[i]) % Mod1;
		ps2 = (ps2 * Factor + P[i]) % Mod2;
	}
	//cout << ps1 << " - " << ps2 << endl;

	int raisedFactor1(1),
		raisedFactor2(1);
	for (int i(0); i < M - 1; ++i) {
		raisedFactor1 = (raisedFactor1 * Factor) % Mod1;
		raisedFactor2 = (raisedFactor2 * Factor) % Mod2;
	}

	int check1(0),
		check2(0);
	int i(0);
	for (; i < M; ++i) {
		check1 = (check1 * Factor + T[i]) % Mod1;
		check2 = (check2 * Factor + T[i]) % Mod2;
	}
	if ((check1 == ps1) && (check2 == ps2))
		matched[mn++] = 0;

	for (; i < N; ++i) {
		check1 = ((check1 - (T[i-M]*raisedFactor1) % Mod1 + Mod1) * Factor + T[i]) % Mod1;
		check2 = ((check2 - (T[i-M]*raisedFactor2) % Mod2 + Mod2) * Factor + T[i]) % Mod2;

		//cout << check1 << " - " << check2 << endl;

		if ((check1 == ps1) && (check2 == ps2))
			if (mn < 1000)
				matched[mn++] = i - M + 1;
			else
				++mn;
		/*if (check1 == ps1) {
			for (int j(0); j < M; ++j)
				if (P[j] != T[i - M + 1 + j])
					continue;
			matched[mn++] = i - M + 1;
		}*/
	}

	fprintf(fout, "%d\n", mn);
	for (i = 0; i < ((mn > 1000) ? (1000) : (mn)); ++i)
		fprintf(fout, "%d ", matched[i]);
	fprintf(fout, "\n");
}

void bmmatch() {
	int d[256];
	for (int i(0); i < 256; ++i)
		d[i] = M;

	for (int i(0); i < M - 1; ++i)
		d[(int)P[i]] = M - i - 1;

	int i = M,
		j,
		k;
	do {
		j = M;
		k = i;
		do {
			--k;
			--j;
		} while ((j >= 0) && (P[j] == T[k]));

		if (j < 0)
			if (mn < 1000)
				matched[mn++] = k + 1;
			else
				++mn;

		i += d[(int)T[i - 1]];
	} while (i <= N);

	fprintf(fout, "%d\n", mn);
	for (i = 0; i < ((mn > 1000) ? (1000) : (mn)); ++i)
		fprintf(fout, "%d ", matched[i]);
	fprintf(fout, "\n");
}

int d[2000002];
void kmpmatch() {
	int j = 0,
		k = -1;
	d[0] = -1;

	while (j < M - 1) {
		while ((k >= 0) && (P[j] != P[k]))
			k = d[k];
		++j;
		++k;
		if (P[j] == P[k])
			d[j] = d[k];
		else
			d[j] = k;
	}

/*	for (int i(0); i < M; ++i)
		cout << P[i] << " ";
	cout << endl;
	for (int i(0); i < M; ++i)
		cout << d[i] << " ";
	cout << endl;*/

	int i = j = k = 0;
	while (i < N) {
		while ((j >= 0) && (T[i] != P[j]))
			j = d[j];
		++i;
		++j;

		if (j == M) {
			if (mn < 1000)
				matched[mn++] = i - M;
			else
				++mn;

			j = 0;
			i = i - M + 1;
		}
	}

	fprintf(fout, "%d\n", mn);
	for (i = 0; i < ((mn > 1000) ? (1000) : (mn)); ++i)
		fprintf(fout, "%d ", matched[i]);
	fprintf(fout, "\n");
}

int main(int argc, char *argv[]) {
	FILE *fin = fopen("strmatch.in", "r");
	fscanf(fin, "%s", P);
	fscanf(fin, "%s", T);
	fclose(fin);

	fout = fopen("strmatch.out", "w");
	M = strlen(P);
	N = strlen(T);

	if (M > N) {
		fprintf(fout, "0\n");
	} else {
		//rkmatch();
		//bmmatch();
		kmpmatch();
	}
	fclose(fout);

	return 0;
}