Cod sursa(job #2273310)

Utilizator cezar.plescaCezar Plesca cezar.plesca Data 31 octombrie 2018 12:49:52
Problema Potrivirea sirurilor Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.03 kb
#include<stdio.h>
#include<string.h>

char cuv[2000001];
char sir[2000001];

int nb;
int poz[2000000];

int base=73;
int p1=100007;
int p2=100021;

// calculul puterii lui b la puterea m-1 modulo p
int computePower(int b,int m,int p){
	int bpower=1;
	for(int i=1;i<=m-1;i++)
		bpower=(bpower*b)%p;
	return bpower;
}

// functia de hash folosita
int hash(char* string, int m, int b, int p,int & B){
	int h=0, bpower=1;
	for(int i=m-1;i>=0;i--){
		h=(h+string[i]*bpower)%p; // actualizarea progresiva a codului
		B=bpower;
		bpower=(bpower*b)%p; // calculul puterilor lui b
	}
	return h;
}

int hashs(char* string, int m, int b, int p){
	int h=0, bpower=1;
	for(int i=m-1;i>=0;i--){
		h=(h+string[i]*bpower)%p; // actualizarea progresiva a codului		
		bpower=(bpower*b)%p; // calculul puterilor lui b
	}
	return h;
}



// algoritmul Rabin-Karp
void rabinkarp(char* pattern, int m, char* text, int n){
	//int B1=computePower(base,m,p1);
	//int B2=computePower(base,m,p2);

	int B1,B2;

	int hp1=hash(pattern,m,base,p1,B1);
	int hp2=hash(pattern,m,base,p2,B2);

	int H1=hashs(text,m,base,p1);
	int H2=hashs(text,m,base,p2);	
	
	int j;
	for(int i=0;i<=n-m;i++){ // potrivire pe pozitia i
		if(H1==hp1 && H2==hp2){
			for(j=0;j<m;j++){ // comparatia cu patternul
				if(text[i+j]!=pattern[j])
					break;
			}
			if(j==m){
				nb++;
				if(nb<=1000)
					poz[nb-1]=i;
				//printf("Potrivire la pozitia % d\n",i);
			}
		}
		if(i<n-m){
			H1=(base*(H1-(text[i]*B1)%p1+p1)+text[m+i])%p1;
			if(H1<0) H1+=p1;

			H2=(base*(H2-(text[i]*B2)%p2+p2)+text[m+i])%p2;
			if(H2<0) H2+=p2;
		}
	}
}

int main(){
	FILE* f= fopen("strmatch.in","rt");
	FILE* g= fopen("strmatch.out","wt");
	
	fscanf(f,"%s",cuv);
	fscanf(f,"%s",sir);

	int m=strlen(cuv);
	int n=strlen(sir);

	if(m>n){
		fprintf(g,"0\n");
		return 0;
	}

	rabinkarp(cuv,m,sir,n);

	fprintf(g,"%d\n",nb);
	for(int i=0;i<nb;i++){
		if(i<1000)
			fprintf(g,"%d ",poz[i]);	
		else
			break;
	}

	fclose(g);
	fclose(f);
	return 0;
}