Cod sursa(job #1181667)

Utilizator omerOmer Cerrahoglu omer Data 3 mai 2014 14:23:00
Problema Substr Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.9 kb
#include<stdio.h>
#include<cstdlib>
#include<time.h>
#include<string.h>
#include<assert.h>
const int N=17000, M=200000;
using namespace std;
FILE *f,*g;

int n,k; char s[N]; int X1, MOD1, INV1; int X2, MOD2, INV2;

int H1[M], H2[M], P1[N], P2[N];

bool prim(int n){
    int k;
    for(k=2;k*k<=n;k++)
        if (n%k == 0) return 0;
    return 1;
}

void read(void){

    f=fopen("substr.in","r");
    g=fopen("substr.out","w");

    fscanf(f,"%d%d",&n,&k);
    fscanf(f,"%s",s);

    for(int i=n; i>=1; i--) s[i]=s[i-1];

    srand(time(NULL));
    srand(time(NULL));
    MOD1=100000+(rand()%100000);
    while (!prim(MOD1)) MOD1=100000+(rand()%100000);

    MOD2=100000+(rand()%100000);
    while (!prim(MOD2)) MOD2=100000+(rand()%100000);

    X1=101; X2=107;

}

void precomp(void){

    P1[0]=P2[0]=1;
    for(int i=1;i<=N-1;i++) {P1[i]=(P1[i-1]*X1)%MOD1; P2[i]=(P2[i-1]*X2)%MOD2;}

    for (INV1=1; INV1; INV1++)  if ((X1*INV1)%MOD1 == 1) break;
    for (INV2=1; INV2; INV2++)  if ((X2*INV2)%MOD2 == 1) break;
}

bool check (int l){

    int hash1=0, hash2=0;  int i;
    memset(H1,0,sizeof(H1));
    memset(H2,0,sizeof(H2));
    
    for(i=1; i<=l ;i++){
        hash1 = (hash1 + (s[i]) * P1[i]) % MOD1;

        hash2 = (hash2 + (s[i]) * P2[i]) % MOD2;
    }
    H1[hash1]++;
    H2[hash2]++;

    for (i=l+1; i<=n; i++){

        hash1 = ((long long)(hash1 + (s[i]) * P1[l+1] - (s[i-l]) * P1[1]) * INV1) % MOD1;
        hash2 = ((long long)(hash2 + (s[i]) * P2[l+1] - (s[i-l]) * P2[1]) * INV2) % MOD2;
       
        H1[hash1]++; H2[hash2]++;
        if (H1[hash1] >= k && H2[hash2] >= k) return 1;
    }

    return 0;

}

int binfind(void){

    int i, step=1;
    
    while (step <= n) step<<=1;
    
    for (i=0; step; step>>=1)
        if (i+step <= n && check(i+step)) i+=step;

    return i;
}

int main(void){

    read();
    precomp();

    if (k == 1) fprintf(g,"%d",n);
    else fprintf(g,"%d",binfind());

    return 0;
}