¿Qué es una forma compacta de representar una partición de un conjunto?

11

Existen estructuras de datos eficientes para representar particiones establecidas. Estas estructuras de datos tienen buenas complejidades de tiempo para operaciones como Union y Find, pero no son particularmente eficientes en cuanto al espacio.

¿Cuál es una forma de espacio eficiente para representar una partición de un conjunto?

Aquí hay un posible punto de partida:

Sé que el número de particiones de un conjunto con elementos es , el número -ésima campana . Entonces, la complejidad espacial óptima para representar una partición de un conjunto con elementos es bits. Para encontrar dicha representación, podríamos buscar un mapeo uno a uno entre (el conjunto de particiones de un conjunto de elementos) y (el conjunto de enteros de a ).B N NNBNNlog 2 ( B N ) N 1 B NNlog2(BN)N1BN

¿Existe tal mapeo que sea eficiente para calcular? Lo que quiero decir con "eficiente" es que quiero convertir esta representación compacta a / de una representación fácil de manipular (como una lista de listas) en un polinomio temporal en o .log 2 ( B N )Nlog2(BN)

cberzan
fuente
preguntándose, ¿qué tan lejos podría estar de la codificación ingenua / natural de solo asignar enteros únicos a cada elemento del conjunto donde el entero representa la partición #? tal vez es "no tanta diferencia" ...log2(BN)
vzn

Respuestas:

7

Puede utilizar la forma en que se deriva la siguiente fórmula de recurrencia para encontrar su codificación: Esto se prueba considerando cuántos otros elementos hay en la parte que contiene el elemento . Si hay de estos, entonces tenemos opciones para ellos, y opciones para dividir el resto.

Bn+1=k=0n(nk)Bk.
n+1nk(nnk)=(nk)Bk

Con esto, podemos dar un algoritmo recursivo para convertir cualquier partición de en un número en el rango . Supongo que ya tiene una forma de convertir un subconjunto de tamaño de a un número en el rango (tal algoritmo puede idearse de la misma manera usando la recurrencia de Pascal ).n+10,,Bn+11k{1,,n}0,,(nk)1(nk)=(n1k)+(n1k1)

Suponga que la parte que contiene contiene otros elementos. Encuentra su código . Calcule una partición de "comprimiendo" todos los elementos restantes en ese rango. Calcular recursivamente su código . El nuevo código esn+1kC1{1,,nk}C2

C=l=0nk1(nl)Bl+C1Bnk+C2.

En la otra dirección, dado un código , encuentre la única tal que y defina Como , puede escribirse como , donde . Ahora codifica los elementos en la parte que contiene , y codifica una partición deCk

l=0nk1(nl)BlC<l=0nk(nl)Bl,
C=Cl=0nk1(nl)Bl.
0C<(nk)BnkC1Bnk+C20C2<BnkC1n+1C2{1,,nk}, que se puede decodificar recursivamente. Para completar la decodificación, debe "descomprimir" la última partición para que contenga todo el elemento que no aparece en la parte que contiene .n+1


Aquí se explica cómo usar la misma técnica para codificar un subconjunto de de tamaño , recursivamente. Si entonces el código es , entonces supongamos que . Si entonces sea ​​un código de , como un subconjunto de tamaño de ; El código de es . Si entonces deje que sea ​​un código de , como un subconjunto de tamaño de ; el código deS{1,,n}kk=00k>0nSC1S{n}k1{1,,n1}SC1nSC1Sk{1,,n1}Ses .C1+(n1k1)

Para decodificar un código , hay dos casos. Si entonces decodifica un subconjunto de de tamaño cuyo código es y la salida . De lo contrario, decodifique un subconjunto de de tamaño cuyo código sea , y envíe .CC<(n1k1)S{1,,n1}k1CS{n}S{1,,n1}kC(n1k1)S

Yuval Filmus
fuente
Excelente respuesta; gracias. Error menor: en el boceto de prueba de la fórmula de recurrencia en la parte superior, creo que quiere decir "hay de esos" en lugar de "hay de esos" - entonces los elementos restantes se pueden dividir en formas . nkkkBk
cberzan