Pagini recente » Cod sursa (job #610932) | Cod sursa (job #1768126) | Cod sursa (job #1603712) | Cod sursa (job #521329) | Cod sursa (job #1765477)
#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
#define MAX(a, b) ( a>b ? a:b )
typedef struct{
int rk1, rk2, next, frecv;
}nod;
nod v[nmax];
char s[16384];
int n, k, ok, max, poz;
int hash[mod];
int cod[123];
int convrabin1[nmax]; ///vector utilizat la operatii asupra nr in baza 62
int convrabin2[nmax]; ///(sterge prima cifra si adauga ulima cifra )
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
for( i='0'; i<='9'; i++ )
cod[i] = i - '0';
for( i='A'; i<='Z'; i++ )
cod[i] = i - 'A' + 10;
for( i='a'; i<='z'; i++ )
cod[i] = i - 'a' + 36;
}
void inithashtable(){ ///sterand vectorul hash se vor pierde informatiile listei
int i;
for( i=0; i<mod; i++ )
hash[i] = 0;
}
void caut( int rabinkarp1, int rabinkarp2 ){
int pozhash;
pozhash = hash[ rabinkarp1%mod ];
for( pozhash = hash[ rabinkarp1%mod ]; pozhash!=0 && ok==0; pozhash = v[pozhash].next ){
if( rabinkarp1 == v[pozhash].rk1 && rabinkarp2 == v[pozhash].rk2 ){
if( v[poz].frecv!=0 ){
max = MAX( max, ++v[poz].frecv );
}
else{
v[++poz].rk1 = rabinkarp1;
v[poz].rk2 = rabinkarp2;
v[poz].next = hash[rabinkarp1%mod];
hash[ rabinkarp1%mod ] = poz;
v[poz].frecv = 1;
}
if( max == k )
ok = 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[i] ) % rabinmod1;
rabinkarp2 = ( rabinkarp2 * baza + cod[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+1;
}
int main()
{
int i;
FILE *fin, *fout;
fin = fopen( "substr.in", "r" );
fscanf( fin, "%d%d\n", &n, &k );
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-1 ) );
fclose( fout );
return 0;
}