Digamos que e são duas cadeias do mesmo comprimento. Uma anagrama de duas strings é um mapeamento bijetivo modo que para cada .b 1 b 2 … b n p : [ 1 … n ] → [ 1 … n ] a i = b p ( i ) i
Pode haver mais de uma anagrama para o mesmo par de cordas. Por exemplo, se `abcab` temos e , entre outros.b = p 1 [ 1 , 2 , 3 , 4 , 5 ] → [ 4 , 5 , 1 , 2 , 3 ] p 2 [ 1 , 2 , 3 , 4 , 5 ] → [ 2 , 5 , 1 , 4 , 3 ]cabab
Vamos dizer que o peso de um anagramador é o número de cortes que se deve fazer na primeira string para obter pedaços que podem ser reorganizados para obter a segunda string. Formalmente, esse é o número de valores de para os quais . Ou seja, ele é o número de pontos em que é que não aumentam por exatamente 1.Para exemplo, e , porque cortes uma vez, para os pedaços e , e cortes quatro vezes, em cinco pedaços.p i ∈ [ 1 … n - 1 ] p ( i ) + 1 ≠ p ( i + 1 ) p w ( p 1 ) = 1 w ( p 2 ) = 4 p 1 p 212345
123
45
12345
Suponha que exista uma anagrama para duas seqüências e . Então, pelo menos uma anagrama deve ter menos peso. Digamos que este seja o mais leve . (Pode haver vários anagramas mais leves; não me importo porque estou interessado apenas nos pesos.)b
Questão
Eu quero um algoritmo que, dadas duas seqüências para as quais existe uma anagrama, produz eficientemente o peso exato da anagrama mais leve das duas seqüências. Tudo bem se o algoritmo também produzir uma anagrama mais leve, mas não precisa.
É uma questão bastante simples gerar todos os anagramas e pesá-los, mas pode haver muitos, então eu preferiria um método que encontre diretamente os anagramas leves.
Motivação
A razão pela qual esse problema é interessante é a seguinte. É muito fácil fazer o computador pesquisar no dicionário e encontrar anagramas, pares de palavras que contêm exatamente as mesmas letras. Mas muitos dos anagramas produzidos são desinteressantes. Por exemplo, os exemplos mais longos encontrados no Segundo Dicionário Internacional do Webster são:
colecistoduodenostomia
duodeno- colecistostomia
O problema deve ser clara: estas são desinteressantes porque eles admitem um anagramming muito leve que simplesmente troca o cholecysto
, duedeno
e stomy
seções, para um peso de 2. Por outro lado, este exemplo muito mais curto é muito mais surpreendente e interessante:
litoral
secional
Aqui, a anagrama mais leve tem peso 8.
Eu tenho um programa que usa esse método para localizar anagramas interessantes, ou seja, aqueles para os quais todos os anagramas são de alto peso. Mas faz isso gerando e pesando todos os anagramas possíveis, o que é lento.
fonte
cholecystoduodenostomy
éccddeehlmnooooossttuyy
.) Duas palavras são anagramas se e somente se elas tiverem a mesma forma canônica. Você armazena as palavras em uma tabela de hash, codificada por suas formas canônicas, e sempre que encontra uma colisão, você tem um anagrama.Respostas:
Esse problema é conhecido como "problema mínimo de partição comum de strings". (Mais precisamente, a resposta no problema mínimo de partição comum de strings é igual à resposta do seu problema mais 1.) Infelizmente, é difícil para NP, mesmo com a restrição de que cada letra ocorre no máximo duas vezes em cada uma das seqüências de entrada, como é comprovado por Goldstein, Kilman e Zheng [GKZ05]. Isso significa que nenhum algoritmo de tempo polinomial existe a menos que P = NP. (Obviamente, se cada letra ocorrer no máximo uma vez, o problema será trivial, pois existe apenas uma anagrama.)
Do lado positivo, os mesmos autores [GKZ05] fornecem um algoritmo de aproximação de tempo polinomial de 1,1037 sob a mesma restrição. (A “1.1037- algoritmo de aproximação ” significa um algoritmo que pode não gerar a resposta correta A, mas que é garantido que gera um valor B tal que A ≤ B ≤ 1.1037 A. ) Eles também fornecem um algoritmo de aproximação linear no tempo linear restrição mais fraca de que cada letra ocorre no máximo três vezes em cada uma das seqüências de entrada.
[GKZ05] Avraham Goldstein, Petr Kolman e Jie Zheng. Problema mínimo de partição comum de strings: Dureza e aproximações. Electronic Journal of Combinatorics , 12, artigo R50, 2005. http://www.combinatorics.org/ojs/index.php/eljc/article/view/v12i1r50
fonte
Este é um seguimento da resposta de Tsuyoshi Ito acima , resumindo a parte mais relevante do documento GKZ05 que ele citou.
O artigo comprova uma redução no problema do Conjunto Independente Máximo ( MIS ). Construa um gráfico cujos vértices são pares modo que e . Vértices de conexão e (onde ) com uma borda, sempre que é impossível que um anagramming pode mapear todos e e e . Isso é fácil de detectar; esse mapeamento é impossível exatamente se um dos seguintes itens for válido:G (i,j) ai=bj ai+1=bj+1 (i,j) (k,ℓ) i≤k i↦j i+1↦j+1 k↦ℓ k+1↦ℓ+1
Digamos que o gráfico resultante tenha um conjunto independente máximo de tamanho . Então o peso mínimo de anagramas é exatamente , onde é o comprimento das cadeias e . (O inverso também vale: uma anagramas de baixo peso se traduz diretamente em um MIS grande para Para obter detalhes, consulte as páginas 4-5 do artigo.)s n - s - 1 n a b GG s n−s−1 n a b G
Por exemplo, considere as duas cadeiass=2
yttrious
etouristy
. O gráfico correspondente possui dois vértices, um para oou
par compartilhado e outro para ori
par compartilhado . Não há arestas entre os vértices, porque é possível ter uma anagrama que mapeiaou
paraou
eri
parari
; ou pode-se verificar se as três condições acima de tudo falham. Portanto, obviamente, o gráfico tem um MIS de tamanho e o peso mínimo de anagramas é de fato 8-2-1 = 5, correspondendo à anagramas ↔ . 'y|t|t|ri|ou|s
t|ou|ri|s|t|y
Por outro lado, considere
derater
etreader
. Desta vez, o gráfico possui três vértices:DErater
+treaDEr
dERater
+treadER
deratER
+treadER
2 e 3 são incompatíveis e 1 e 3 são incompatíveis, mas 1 e 2 são compatíveis. Portanto, o MIS exclusivo tem tamanho e contém os vértices 1 e 2. A anagrama correspondente do peso 7-2-1 = 4 é ↔ .s=2
der|a|t|e|r
t|r|e|a|der
fonte
Ele não cobre o algoritmo exato que você tinha em mente (como responde a resposta de Tsuyoshi Ito ), mas tenta entender o problema subjacente de encontrar anagramas "interessantes" ...
Meu primeiro pensamento foi usar alguma variação na distância de edição, onde as alterações atômicas são ponderadas de acordo com sua "interessante", e não com as habituais ponderações de "dificuldade" ou "confusabilidade". Obviamente, parece improvável que você possa codificar eficientemente as transformações realmente interessantes dessa maneira, pois elas provavelmente não são locais e, portanto, se deparam com os problemas de MIS etc. do NP-completos.
Assim, o segundo pensamento seria construir um alinhamento letra a letra entre as palavras (à la alinhamento de tradução automática) e depois pontuar os alinhamentos por "interesse" (por exemplo, contar os alinhamentos que levam letras adjacentes a não- letras adjacentes, ou quantos alinhamentos cada alinhamento cruza, etc; e depois combine todos eles via modelo loglinear ou similar).
A terceira idéia é abandonar completamente a estrutura da anagramas e, em vez disso, a semântica das palavras. Freqüentemente, o que torna um anagrama "interessante" é a incongruência entre os significados das palavras envolvidas. Portanto, tente algo como calcular a distância deles no WordNet ou similar.
fonte
O problema pode ser formulado em termos de grupos de permutação .
Agora, um grupo de permutação contém todos os "movimentos do anagrama", tanto primitivos (trocando duas letras) quanto compostos de sequências de movimentos primitivos. Parece que você está interessado em apenas um subconjunto das permutações possíveis. Vou tentar definir isso.
Primeiro, lembre-se da notação de permutações, a chamada notação de ciclo :
Esses "ciclos" simples são compostos para descrever permutações mais complexas.
Parece que os movimentos nos quais você está interessado são (para uma palavra de comprimento ):n
Esses movimentos formam a base do seu algoritmo. O que você está interessado é encontrar a menor seqüência desses movimentos para passar de uma palavra para a seguinte.
Não conheço nenhum algoritmo para calcular isso, além da busca por força bruta, mas pelo menos agora há uma descrição mais clara (espero) do que são os movimentos primitivos. (E talvez algum teórico de grupo entre nós possa apontar para um algoritmo apropriado.)
fonte
Para colecistoduodenostomia / duodenocoliolecistostomo, notei que se você atribuísse um número a cada caractere descrevendo o quanto ele foi movido como um delta, você teria algo como 7 7, depois 8 -7 s e 6 0. Isso não está certo, porque alguns caracteres podem ter sido repetidos (o segundo c avançou apenas 2, não retornou 7) etc. etc, mas ainda é muito "codificável no comprimento da execução" porque você vê os mesmos deltas seguidos.
Compare com o litoral / seção, em que você vê algo como (+2) (+ 5) (+ 5) (- 3) (- 1) (+ 3) ... e muito menos "duração da codificação".
Talvez a aleatoriedade dos deltas possa lhe dar uma "pontuação" de quão interessante é o anagrama?
fonte