Encontrar anagramas interessantes

31

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 2b n p : [ 1 n ] [ 1 n ] a i = b p ( i ) ia1a2anb1b2bnp:[1n][1n]ai=bp(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 ]a=b=cababp1[1,2,3,4,5][4,5,1,2,3]p2[1,2,3,4,5][2,5,1,4,3]

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 2w(p)pi[1n1]p(i)+1p(i+1)pw(p1)=1w(p2)=4p11234512345p212345

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.)bab

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, duedenoe stomyseçõ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.

Mark Dominus
fonte
Por curiosidade, como você encontra pares de anagramas? Você faz uma pesquisa de força bruta com todas as palavras do mesmo comprimento? O(n2)
Pedro
4
Não, claro que não. Você converte cada palavra em uma forma canônica que possui as mesmas letras em ordem alfabética. (Por exemplo, a forma canônica de 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.
Mark Dominus
Agora tenho uma grande quantidade de mais ou menos relacionadas com informações sobre isso no meu blog: (α) (β) (γ) (δ)
Mark Dominus

Respostas:

21

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 AB ≤ 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

Tsuyoshi Ito
fonte
9

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=bjai+1=bj+1(i,j)(k,)ikiji+1j+1kk+1+1

  1. i=k ej
  2. j + 1 i+1=k ej+1
  3. { j , j + 1 } { , + 1 }i+1<k e é separado de{j,j+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 GGsns1nabG

Por exemplo, considere as duas cadeias yttriouse touristy. O gráfico correspondente possui dois vértices, um para o oupar compartilhado e outro para o ripar compartilhado . Não há arestas entre os vértices, porque é possível ter uma anagrama que mapeia oupara oue ripara ri; 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 ↔ . 's=2y|t|t|ri|ou|st|ou|ri|s|t|y

Por outro lado, considere deratere treader. Desta vez, o gráfico possui três vértices:

  1. DErater + treaDEr
  2. dERater + treadER
  3. 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=2der|a|t|e|rt|r|e|a|der

Mark Dominus
fonte
2
Obrigado pela postagem de acompanhamento, mas essa não é uma prova da integridade do NP do seu problema. Para provar a NP-completude do seu problema, você deve reduzir um problema conhecido de NP-complete ao seu problema, e esse é o Teorema 2.2 de [GKZ05]. O que você apresentou aqui (Lema 1.1 de [GKZ05]) é uma redução na direção oposta.
Tsuyoshi Ito
Esta é uma bela reformulação. Uma mudança trivial que é uma simplificação menor conceitualmente (pelo menos para mim): em vez de desenhar arestas entre pares incompatíveis e solicitar o conjunto independente máximo, podemos desenhar arestas entre pares compatíveis e solicitar a camarilha máxima. (Acho mais fácil pensar em "qual é o número máximo de pares que podemos manter juntos").
ShreevatsaR
2

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.

wren romano
fonte
0

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 :

  • () significa sem permutação.
  • (1) significa que 1 é trocado por 1, o que também não é permutação.
  • (12) meios 1 e 2 são trocados.
  • (123) significa 1 substitui 2 que substitui 3 que substituem 1 (uma rotação).
  • e então um

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

  • swaps de pares de caracteres únicos: são os swaps como(12)
  • permutas de pares de caracteres consecutivos 2: estes são permutações da forma , onde e e(a b)(a+1 b+1)a>0b<a+1b+1n
  • ...
  • trocas de pares de n caracteres consecutivos: são permutações da forma que , , e .a > 0 a + i - 1 b b + i - 1 n(a b)(a+1 b+1)(a+i1 b+i1)a>0a+i1bb+i1n

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.)

Dave Clarke
fonte
1
Obrigado. Talvez eu esteja sendo pessimista, mas parece-me que essa abordagem será difícil. Não acho que uma abordagem teórica de grupo traga frutos, a menos que primeiro descubramos qual grupo de permutação é de interesse, e isso varia dependendo das seqüências de entrada. Penso que a representação eficiente de grupos finitos é um problema extremamente profundo e rico. Mas eu gostaria de estar enganado.
Mark Dominus
1
“O que você está interessado é encontrar a menor seqüência desses movimentos para passar de uma palavra para a outra.” Não acho que isso esteja correto. Por exemplo, se n = 4, o swap (1 2) tem peso 2, mas o swap (2 3) tem peso 3. Sua maneira de contar não distingue esses dois.
Tsuyoshi Ito
Eu respondi tarde da noite. Não entendi a medida do peso corretamente. Na verdade, eu não entendo isso agora. Eu pensei que você queria permitir movimentos de blocos de letras, e foi por isso que me dei ao trabalho de definir essas primitivas. Minha resposta pode fornecer inspiração, por isso vou deixá-la, mesmo que esteja errada.
18760 Dave
0

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?

Dan Gelder
fonte