Pagini recente » Cod sursa (job #1102289) | Cod sursa (job #1180828) | Cod sursa (job #1696885) | Cod sursa (job #1164110) | Cod sursa (job #1765619)
#include <stdio.h>
#define nmax 16384
#define baza 62 ///baza cu cifre, litere mari si litere mici
#define mod 702113
#define rabinmod1 191707
#define rabinmod2 120569
typedef struct{
int rk1, rk2, next, frecv;
}nod;
nod v[nmax+1];
char s[16384];
int n, k, ok, max, poz;
int hash[mod]; ///capul listei
int cod[123]; ///convertim fiecafre caracter la baza 62
int convrabin1[nmax]; ///vector utilizat la operatii asupra nr in baza 62
int convrabin2[nmax]; ///(sterge prima cifra si adauga ulima cifra )
int MAX( int x, int y ){
return x>y ? x:y;
}
void initbaza(){
int i;
///numere care sunt multiplii bazei pt a sterge prima cifra
convrabin1[0] = convrabin2[0] = 1;
for( i=1; i<=n; i++ ){
convrabin1[i] = ( convrabin1[i-1] * baza ) % rabinmod1;
convrabin2[i] = ( convrabin2[i-1] * baza ) % rabinmod2;
}
///conversia caracterelor la baza 62
char c;
for( c='0'; c<='9'; c++ )
cod[c] = c - '0';
for( c='A'; c<='Z'; c++ )
cod[c] = c - 'A' + 10;
for( c='a'; c<='z'; c++ )
cod[c] = c - 'a' + 36;
}
void inithashtable(){ ///sterand vectorul hash se vor pierde informatiile listei
int i;
for( i=poz=0; i<mod; i++ )
hash[i] = 0;
}
void caut( int rabinkarp1, int rabinkarp2 ){
int pozhash, adauga=1;
for( pozhash = hash[ rabinkarp1%mod ]; pozhash!=0 && adauga==1; pozhash = v[pozhash].next ){///caut elementul ce se incadreza cu cele 2 hash-uri
if( rabinkarp1 == v[pozhash].rk1 && rabinkarp2 == v[pozhash].rk2 ){
adauga = 0;
max = MAX( max, ++v[pozhash].frecv ); /// incrementez nr aparitii si calculez noul maxim
if( max == k ) ///daca am gasit o secventa cu lungimea minima k
ok = 1;
}
}
if( adauga==1 ){ ///daca nu exista acest nr in lista
v[++poz].rk1 = rabinkarp1; ///hash nr 1
v[poz].rk2 = rabinkarp2; ///hash nr 2
v[poz].next = hash[rabinkarp1%mod]; ///lista
hash[ rabinkarp1%mod ] = poz; ///capul listei
v[poz].frecv = 1;
}
}
int gasit( int lung ){
int i, rabinkarp1, rabinkarp2;
rabinkarp1 = rabinkarp2 = 0;
max = 1;
inithashtable(); ///reinitializam capul ce va determina reinitializarea listei
ok = 0; ///daca nu am gasit un subsir de acea dimensiune ce apare de minim k ori
for( i=0; i<lung; i++ ){ ///determinam hash numarului de la inceput pana la nrcaractere-1 al subsirului actual
rabinkarp1 = ( rabinkarp1 * baza + cod[ s[i] ] ) % rabinmod1;
rabinkarp2 = ( rabinkarp2 * baza + cod[ s[i] ] ) % rabinmod2;
}
for( i=lung; i<n && ok==0; i++ ){
rabinkarp1 = ( rabinkarp1 * baza + cod[ s[i] ] ) % rabinmod1;
rabinkarp2 = ( rabinkarp2 * baza + cod[ s[i] ] ) % rabinmod2;
caut( rabinkarp1, rabinkarp2 ); ///cautam daca apare acest nr in lista
///eliminam prima cifra
rabinkarp1 = ( ( rabinkarp1 - convrabin1[ lung ] * cod[ s[ i-lung] ] ) % rabinmod1 + rabinmod1 ) % rabinmod1;
rabinkarp2 = ( ( rabinkarp2 - convrabin2[ lung ] * cod[ s[ i-lung] ] ) % rabinmod2 + rabinmod2 ) % rabinmod2;
}
return( max>= k );
}
int sol( int start, int stop ){ ///realizam o cautare binare pt gasirea lungimii sirului
int mij;
while( stop-start>1 ){
mij = ( start + stop ) >> 1;
if( gasit(mij) == 1 ) ///daca am gasit un subsir ce apare de minim k ori, avansam cu inceputul
start = mij; ///ce va determina cresterea mojlocului, si implicit lungimea subsirului pt urmatoarea cautare
else
stop = mij; ///daca nu l-am gasit, micsoram dimensiunea subsirului prin reducerea mijlocului
}
return stop;
}
int main()
{
int i;
FILE *fin, *fout;
fin = fopen( "substr.in", "r" );
fscanf( fin, "%d%d", &n, &k );
fgetc( fin ); ///citim in gol caracterul '\n'
for( i=0; i<n; i++ )
s[i] = fgetc( fin ); ///citim sirul
fclose( fin );
fout = fopen( "substr.out", "w" );
///initializam vectori pt converisa mai usoara la baza 62
initbaza();
fprintf( fout, "%d\n", sol( 0, n ) );
fclose( fout );
return 0;
}