Existe uma função hash para uma coleção (ou seja, vários conjuntos) de números inteiros que possui boas garantias teóricas?

36

Estou curioso para saber se existe uma maneira de armazenar um hash de um conjunto múltiplo de números inteiros que possua as seguintes propriedades, idealmente:

  1. Utiliza espaço O (1)
  2. Pode ser atualizado para refletir uma inserção ou exclusão no tempo O (1)
  3. Duas coleções idênticas (ou seja, coleções que possuem os mesmos elementos com as mesmas multiplicidades) devem sempre hash para o mesmo valor e duas coleções distintas devem hash para valores diferentes com alta probabilidade (ou seja, a função é independente ou independente em pares)

Uma tentativa inicial seria armazenar o módulo do produto como um primo aleatório dos hashes dos elementos individuais. Isso satisfaz 1 e 2, mas não está claro se, ou uma variação aproximada, satisfaria 3.

Originalmente, eu postei isso no StackOverflow .

* As propriedades 1 e 2 podem ser relaxadas um pouco para, digamos, O (log n) ou um pequeno polinômio sublinear. O objetivo é ver se podemos identificar vários conjuntos e testar de forma confiável a igualdade sem armazenar os próprios elementos.

jonderry
fonte
Qual é a sua representação de vários conjuntos? Ou seja, como você codifica um multiset como uma string de bits? Se você realmente deseja obter operações em tempo O(1) (independentemente do tamanho do multiset), acho que você deve tornar a codificação explícita.
Jukka Suomela
A codificação dos conjuntos não é importante. A função hash deve ser independente da representação dos conjuntos. Se eu estivesse usando uma representação canônica de um conjunto de hash, qualquer hash padrão na representação de bits do conjunto satisfaria 3 e provavelmente 1, mas não 2. Devo acrescentar que duas coleções iguais sempre devem hash com o mesmo valor.
jonderry
O que exatamente você quer dizer com 2? Você obtém o conjunto antigo, o código hash antigo e o novo elemento, e deseja calcular o novo código hash? Ou você obtém apenas o código hash antigo e o novo elemento?
Mihai
Idealmente, você não precisaria do conjunto antigo. Você nem precisa ser capaz de executar consultas de membros (importante, considerando os limites de espaço), apenas testes de igualdade, provavelmente através da comparação de valores de hash com baixa probabilidade de falso positivo.
jonderry

Respostas:

17

Se você pensa em conjuntos como vivendo no universo , é muito fácil resolver seu problema com o tempo de atualização O ( lg u ) . Tudo que você precisa é de uma função rápida de hash para um vetor de números u , com rápidas "atualizações locais".[u]O(lgu)u

h(x)=(i=1uxiai)modpuma [ p ] i um i O ( lg i ) u u S ( u / p ) p p = u 2 [ u ]pa[p]iaiO(lgi)uuO(u/p) . Isso pode ser muito pequeno considerando que seja grande o suficiente (por exemplo, e você trabalha com "precisão dupla"). Se os conjuntos são muito menores que , é claro que você pode começar por fazer o universo se transformar em um universo menor.pp=u2[u]

Alguém conhece uma solução com probabilidade de colisão ao fazer o hash no intervalo ? Isso deveria ser possível.[ p ]O(1/p)[p]

Mihai
fonte
0

Carter e Wegman abordam isso em Novas funções de hash e seu uso na autenticação e na igualdade de conjuntos ; é muito parecido com o que você descreve. Essencialmente, uma função hash comutativa pode ser atualizada um elemento por vez para inserções e exclusões e correspondências de alta probabilidade, em O (1).

KWillets
fonte
Eu acho que isso funciona apenas em conjuntos, não em vários conjuntos (como a pergunta solicitada). Na seção 5, na parte inferior da página 274: "ADICIONAR (x, S) - adiciona o elemento x ao conjunto denominado S. Esta operação não pode ser usada se x já for um membro de S."
jbapple
Você está certo; Eu perdi a parte "multi". Parece provável que uma função hash possa manipular duplicatas, embora eu não tenha uma citação para isso.
KWillets
-2

A qualidade de uma função de hash sempre dependerá das propriedades dos elementos que ele tem para o hash. Você pode dizer algo sobre isso? Por exemplo, a sugestão do seu produto provavelmente é uma função de hash ruim se os elementos x_i do seu multiset normalmente tiverem muitos fatores primos pequenos. Mas você pode melhorá-lo neste caso simplesmente usando o produto de todos os x_i + p mod q para alguns primos peq.

TonyK
fonte
1
Sim, essa é a razão para usar os hashes dos elementos individuais antes de multiplicá-los.
jonderry
O que? A sugestão do OP é simplesmente multiplicá-los todos juntos, não é? Estou dizendo que se você adicionar uma constante a cada uma antes de fazer isso, provavelmente obterá um hash melhor.
TonyK 01/12/19
-5
A = 0x4F1BBCDD
B = 0x314EFB75
A*B = 1 
N = size of set before addition/removal<P>
Add X
H = (H-N)*B
U = H >> 16
V = H & 0xFFFF
H = (((U+X)&M)<<16) + ((V^X)&M)
H *= A
H += N+1

Remove X
H = (H-N)*B
U = H >> 16
V = H & 0xFFFF
H = (((U-X)&M)<<16) + ((V^X)&M)
H *= A
H += N-1

a soma nos permite ter várias ocorrências do mesmo valor,
o xor nos permite ter conjuntos que somam a mesma quantidade

Louis Reinitz
fonte