2009-04-09 7 views
10

Il dominio di interesse è la corrispondenza delle stringhe. Supponiamo che io abbia una struttura come questa.Come andresti a progettare una funzione per un hash perfetto?

typedef struct 
{ 
    char *name, 
    int (*function)(); 

} StringArray 

StringArray s[] = 
{ 
    {"George", func1}, 
    {"Paul", func2}, 
    {"Ringo", func3}, 
    {"John", func4}, 
    {"",  NULL} /* End of list */ 
} 

C'è un numero fisso di stringhe nell'array. Sono hardcoded come nell'esempio. Se la tabella cambia, è necessario rivalutare la qualità della funzione di hash.

Desidero applicare una funzione di hash a una stringa e, se la stringa corrisponde a una nell'array, chiamare la funzione . Per questo è necessaria una perfetta funzione di hash. Nessuna collisione è consentita. Lo scopo di richiedere l'hashing è quello di ottenere prestazioni O (1) nella ricerca.

Che idee avete nel progettare una funzione per fare questo?

+0

Non credo che lo spam significa ciò che si pensa significhi –

+0

@Mitch: Vuoi dire questa è una domanda che potrebbe essere facilmente su google per? –

+0

@ j_random_hacker: l'ho fatto. Ma è tardi, e non è spam ... –

risposta

16

Vedere la gperf home page.

+0

La parte del gabbiano è che c'è un collegamento a questo nella parte inferiore della pagina di Wikipedia. – EvilTeach

0

È possibile utilizzare la mappa

std::string foo() { return "Foo"; } 
std::string bar() { return "Bar"; } 

int main() 
{ 
    std::map<std::string, std::string (*)()> m; 
    m["foo"] = &foo; 
    m["bar"] = &bar; 
} 
+0

std :: mappa non usa un hash - è basato sull'albero –

+0

perché inventare la ruota, puoi usare le librerie esistenti come la mappa. – Vinay

+1

forse l'interrogante voleva le caratteristiche di performance dell'hash piuttosto che quelle della ricerca ad albero? –

1
+0

Non indirizza direttamente la domanda, ma comunque buoni collegamenti. – EvilTeach

+0

Sarebbe il downvoter (a questa domanda molto vecchia) si prega di lasciare un commento. Grazie. –

0

Se le collisioni sono assolutamente non ammessi, l'unica opzione è quella di tenere traccia di ogni stringa nel database, che probabilmente non è un modo migliore per partire.

Quello che vorrei fare è applicare uno degli algoritmi di hashing più comuni, come MD5 o SHA. Ci sono miriadi di campioni in tutto, eccone uno per esempio: http://www.codeproject.com/KB/security/cryptest.aspx

-1

Bene, non esiste una funzione di hash perfetta.

Ne esistono diverse che riducono al minimo le collisioni, ma nessuna le elimina.

non posso consigliare un però: P

EDIT: La soluzione non può essere trovare una funzione di hash perfetta. La soluzione è essere consapevoli delle collisioni. Generalmente una funzione hash ha collisioni. Questo ovviamente dipende dal set di dati e dalla dimensione del codice hash risultante.

+0

http://en.wikipedia.org/wiki/Perfect_hashing –

+0

@Adam: C'è un avvertimento abbastanza grande in quanto viene applicato solo quando è presente un set di dati distinto. Dato che l'OP non ha fatto alcun accenno al limitare le stringhe in uso, sono d'accordo con Megacan che in questo caso non esiste un hash perfetto. +1. – sipwiz

+0

L'interrogante fa quella menzione, almeno implicitamente - c'erano solo quattro Beatles) o siz se includi il batterista che hanno licenziato e Stu whatsisname) - ancora, un set di dati fisso. –

0

Utilizzare un albero binario bilanciato. Quindi il tuo comportamento KNOW è SEMPRE O (logn).

Non mi piacciono gli hash. Le persone non si rendono conto di quanto rischio assumano con il loro algoritmo. Eseguono alcuni dati di test e quindi si distribuiscono sul campo. Non ho mai visto un algoritmo di hash distribuito controllato per il comportamento nel campo.

O (log n) è quasi sempre accettabile al posto di O (1).

+0

"O (log n) è quasi sempre accettabile al posto di O (1)." In molte applicazioni, questa affermazione è completamente sbagliata. Basta aumentare il numero di punti di dati a pochi milioni per vederlo. –

+0

Una volta fatto, prova. Gli hash non danno risultati garantiti, a meno che tu non sappia in anticipo quali possono essere tutti gli input possibili. Una funzione di hash che tende a raggruppare l'input probabilmente non ti darà O (1). –

+0

In questo caso, tutti gli input sono noti. Sono seduti nella schiera. e la stringa di input è una corrispondenza esatta o una non corrispondenza. – EvilTeach

2

Il sommario elenca sia C che C++. Quale di loro stai cercando? C e C++ sono due linguaggi distinti e si differenziano notevolmente per la gestione delle stringhe e le strutture dati (e il fatto che le C funzionino in C++ non lo cambia).

Perché, in particolare, vuoi una perfetta funzione di hash? Vuoi associare una stringa a una funzione e pensare che sarebbe un buon modo per farlo? È una specie di compito a casa? Hai un motivo per non utilizzare la mappa <> in C++? (Oppure unordered_map <> se disponibile?)

Se hai bisogno di un hash perfetto, quali sono i vincoli sulle stringhe? Ci sarà un certo set fisso su cui vuoi effettuare l'invio? Che dire delle stringhe che non corrispondono a quelle del set? Sei disposto ad accettare hit da stringhe casuali o il numero di stringhe in entrata è limitato?

Se potessi modificare la tua domanda per includere informazioni del genere, potremmo essere molto più utili.

EDIT (in risposta ai primi due commenti):

OK, dovremmo esaminare soluzioni C, dal momento che si desidera probabilmente questo sia per il vostro lavoro C e C++. Preferibilmente vuoi la performance, ma hai provato? Se abbiamo a che fare con le stringhe che entrano nel sistema I/O, è probabile che il tempo non superi il tempo di invio.

Ci si aspetta stringhe arbitrarie. È un po 'troppo aspettarsi una perfetta funzione di hash che eviti tutte le collisioni da dati casuali, quindi è necessario tenerne conto.

Avete considerato un trie? Potrebbe essere più efficiente di una perfetta funzione di hash (o potrebbe non esserlo), dovrebbe essere abbastanza facile da implementare in C, ed eviterà problemi con la ripetizione dell'elenco di stringhe di dispacciamento o possibili collisioni.

+0

Codice in sia in c che in C++ e dio mi aiuti Pro * C. O (1) hashing per prestazioni. Lol, nessun compito a casa. Sto cercando di costruire uno strumento per accelerare il codice critico delle prestazioni. L'esempio è reso semplice per scopi di discussione. L'uso del mondo reale non lo è. – EvilTeach

+0

Le stringhe saranno molto lunghe. Nessuno di essi sarà di lunghezza zero. Come limite pratico, nessuna stringa nell'array sarà più lunga di 32 caratteri. Ciò che passa il chiamante può essere di qualsiasi lunghezza, ma se è più lungo delle stringhe nella tabella, è il caso di un non corrispondente – EvilTeach

+0

+1 per aver menzionato il trie. –

0

Il risultato finale di questo esercizio era di

  • rubare un certo numero di funzioni hash corda orientata dalla rete.
  • Costruire una sorta di classe factory che ha testato ciascuna funzione rispetto al set di dati con un intervallo di valori operatore mod, cercando l'hash più piccolo perfetto che funzioni con quella funzione.
  • Questo costruttore predefinito della classe factory restituisce una stringa, che rappresenta un insieme di argomenti che quando si utilizza la funzione hash corretta e la dimensione della mod per fornire l'hash perfetto che richiede la minor quantità di memoria.
  • in condizioni di utilizzo normale, si semplifica l'istanza della classe con gli argomenti restituiti e la classe si mette in uno stato funzionante con le funzioni desiderate.
  • Questo costruttore convalida che non ci sono collisioni e si interrompe se ci sono.
  • Nel caso in cui non venga trovato un hash perfetto, degrada in una ricerca binaria su una versione ordinata della tabella di input.

Per il set di matrici che ho nel mio dominio, questo sembra funzionare molto molto bene. Una possibile ottimizzazione futura sarebbe quella di eseguire lo stesso tipo di test, su sottostringhe dell'input. Nel caso di esempio, la prima lettera del nome di ogni musicista è sufficiente per distinguerli. Quindi è necessario bilanciare il costo dell'effettiva funzione di hash contro della memoria utilizzata.

Grazie a tutti coloro che hanno contribuito con le idee.

Male