/* Contact (IOI 1998) Copyright (C) 2000 Sebastiano Vigna This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Il programma di per se' e` piuttosto banale: dato che i pattern richiesti sono corti, e` possibile creare un vettore di occorrenze indiciato dal valore numerico dei pattern. Ci sono pero` numerosi dettagli che possono indurre in errore: innanzitutto affinche' l'indicizzazione funzioni occorre prefissare i pattern con 1 (altrimenti 00 e 000 avrebbero lo stesso indice). Inoltre l'inizio e la fine della stringa di input sono molto rognosi. */ #include #include #include #include #include #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define MINLUNPATT 1 #define MAXLUNPATT 12 #define NUMPATT 20 int occ[1<<(MAXLUNPATT+1)]; /* Misura le occorrenze dei pattern; il pattern p e` indiciato da 1p (cosi`, per esempio, 00 e 000 hanno indici diversi--100 (decimale 8) e 1000 (decimale 16). */ /* Questa funzione stampa un indice in binario. Prima di tutto cerchiamo il bit a uno piu` a sinistra. Quindi lo saltiamo e stampiamo i rimanenti. */ void stampaindice(int n) { int i; for(i=MAXLUNPATT+1; i>=0; i--) if (1<=0; i--) printf("%d", (n & 1<= B) for(i=A; i<=B; i++) { occ[t]++; t >>= 1; } } /* Quando l'input e` esaurito, abbiamo comunque dentro p diversi pattern da leggere: sono quelli che si ottengono eliminando via via un bit a sinistra di p. Si noti che la lunghezza corrente di p e` min(B, lungh), e che se lungh < B non e` stato preso ancora in considerazione alcun pattern. */ for(i=min(B, lungh+1)-1; i>=A; i--) { t = p = p & ~(~0 << i) | (1<>= 1; } } /* Per estrarre i massimi, non facciamo troppo sforzo: scandiamo il vettore occ per trovare il massimo valore, e quindi lo riscandiamo per stampare in ordine di valore numerico i vari pattern. Si noti che l'indicizzazione che abbiamo scelto fa apparire facilmente nell'ordine corretto i pattern: infatti se la stringa s e` piu` lunga della stringa t il suo indice e` maggiore, dato che contiene un 1 in una posizione piu` a sinistra, e se s e t hanno la stessa lunghezza sono ordinate sulla base del loro valore numerico. */ do { M = INT_MIN; /* Troviamo il massimo delle occorrenze */ for(i=0; i<(1<<(B+1)); i++) M = max(M, occ[i]); /* Dobbiamo stampare solo pattern che sono comparsi qualche volta. */ if (M == 0) break; printf("%d", M); for(i=(1<<(B+1)); i>=0; i--) /* Questa volta dobbiamo scandire il vettore in ordine inverso. */ if (occ[i] == M) { printf(" "); stampaindice(i); occ[i] = 0; /* Ogni volta che stampiamo una stringa mettiamo a zero il suo numero di occorrenze, in modo da non riconsiderarla. */ } printf("\n"); } while(--N); }