Um algoritmo de pesquisa de subconjunto


9

Suponha que eu tenho uma lista de subconjuntos de { 1 , . . . , n } . Eu posso fazer o pré-processamento nesta lista, se necessário. Após este pré-processamento, eu sou apresentado com um outro conjunto A { 1 , . . . , n } . Quero identificar quaisquer conjuntos B X com B A .X{1,...,n}A{1,...,n}BXBA

O algoritmo óbvio (sem nenhum pré-processamento) leva tempo - você simplesmente testa A contra cada B X separadamente. Existe algo melhor que isso?O(n|X|)ABX

Se ajudar, você pode assumir que, para qualquer , o número total de correspondências B X é limitado por algo como O ( 1 ) .ABXO(1)

Respostas:


3

Esta não é uma resposta. É uma observação simples, mas longa. Espero que seja útil.

A versão de decisão do seu problema é: X contém um subconjunto de A ?

n{1,,n}nXfnffg(y)=(xy,f(x))g(A)f=gfX

fgggΩ((nn/2))

Mas (1) uma análise melhor pode ser possível e (2) pode haver ajustes nessa abordagem que a tornam melhor. Por exemplo, eu não usei de forma alguma a correlação entre o tamanho de e o tamanho do BDD de . (Deve haver uma correlação, mas não sei se é simples ou utilizável aqui.)Xg

Para completar, um algoritmo simples para calcular o BDD for partir do BDD for é o seguinte. Aqui é a operação ou operação padrão nos BDDs.gf

m(x?f1:f0)=x?(m(f0)m(f1)):m(f0)

2
Isso não é mais ou menos equivalente a pré-calcular a resposta para cada subconjunto de , armazenando em cache todos os resultados em uma árvore binária de tamanho e, em seguida, procurando a direita resultado (no tempo ) quando você recebe ? {1,2,...,n}2nO(n)A
precisa saber é o seguinte

Usar espaço exponencial para armazenar dados pré-processados ​​parece trapaça para mim, embora não seja proibido na pergunta. Mas posso ser tendencioso em relação à Igreja da Pior Complexidade.
Tsuyoshi Ito

mjqxxxx e Tsuyoshi: Eu concordo com vocês dois. Reescrevi o texto para que, espero, fique mais claro que concordo. :)
Radu GRIGore

3

Talvez você possa usar uma técnica de "recuperação de informações": na fase de pré-processamento, crie um índice invertido (no seu caso, é suficiente uma matriz bidimensional ) que mapeia um elemento para os conjuntos em que o contêm: .n×|X|xi{1,...,n}Xinv(xi)={XjX|xiXj}

Configure um array inteiro de comprimento.occ|X|

Então, para cada recupera , e para cada ocorreyiAinv(yi)Xjinv(yi)occ[j]=occ[j]+1

No final, os conjuntos necessários são aqueles para os quais .|Xj|=occ[j]

Você pode acelerar arbitrariamente o processo (ao custo do espaço exponencial) indexando dois ou mais elementos juntos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.