Algoritmo mais rápido para encontrar a subsequência palindrome mais longa

8

Antes de tudo, devemos ler uma palavra e o tamanho desejado.
Então precisamos encontrar o palíndromo mais longo criado por caracteres nesta palavra, usado em ordem.
Por exemplo, para tamanho = 7 e palavra = "abcababac", a resposta é 7 ("abababa").

Postscript: o tamanho da palavra é menor que 3000.

Gilles 'SO- parar de ser mau'
fonte
Com max palindrome, você quer dizer que você pode excluir caracteres da string para deixar um palindrome e deseja o palindrome mais longo (ou remoção mínima)?
1
No seu exemplo, também há cababac de comprimento 7. Os caracteres removidos ficam próximos um do outro e no final. Você tem uma dessas restrições? Eles simplificam bastante a pesquisa.
6
Isso já foi respondido no Stack Overflow: como encontrar a subsequência palindrômica mais longa?
@GenericHuman: A melhor resposta nessa pergunta foi boa para o capítulo do livro que o autor estava lendo. Não é uma boa resposta para esse solicitante. Veja esta pergunta: stackoverflow.com/questions/7043778/… .
Neil G
1
Como o tamanho é usado? Você diz que deseja o "max palíndromo", e daí se o palíndromo mais longo for maior ou menor que o tamanho especificado?
Gilles 'SO- stop be evil'

Respostas:

6

Existe um algoritmo com o nome do algoritmo de Manacher, que é realmente rápido, um algoritmo de tempo linear.

Veja a referência da Wikipedia


Pós-escrito: Se você realmente conhece o algoritmo Z , verá que eles são parecidos.


Editar

Entendi mal o significado do OP (mas não quero excluir as informações de procedimento. É um pouco útil). Ele significa a subsequência palíndrica mais longa de uma string, portanto a programação dinâmica parece boa: onde denota o comprimento da maior subsequência palíndrica de , e é o suporte de Iverson. Eu acho que é como LCS .

fj,k=max(fj,k+1,fj+1,k,2[Sj=Sk]+fj+1,k1),j<kfk,k=1fj,k=0,j>k
fj,kSj..k[P]
Yai0Phah
fonte
4
Você está respondendo no caso de substring, mas a pergunta é sobre subsequências.
O primeiro termo não deveria ser f (j, k-1)?
Abhishek Bansal
5

O algoritmo mais rápido que consigo pensar é aplicar o LCS de maneira criativa. Ele pode resolver esse problema no tempo O (N ^ 2) e no espaço O (N ^ 2) em que N é o tamanho da string.

LCS (S, reverso (S)) fornecerá a maior subsequência palindrômica, pois a maior subsequência palindrômica será a maior subsequência comum entre a cadeia S e seu inverso.

Por exemplo,
S = "abcababac"
T = "cababacba" (reverso de S)
LCS (S, T) = "abababa"

Shashwat
fonte
Você pode argumentar que esse algoritmo é o mais rápido que alguém pode apresentar, como a pergunta está sendo feita?
Juho
@ Juho: Eu não posso. :( Este é o algoritmo mais rápido que conheço. No entanto, ele foi aceito no juiz on-line da UVA ( uva.onlinejudge.org/external/114/11404.html ) e no ACM as restrições de problemas são tais que somente a solução otimizada será aprovada. Daí a solução é rápido o suficiente, não tenho certeza sobre o mais rápido.
Shashwat
2

O problema de encontrar o LPS de uma string pode ser convertido em encontrar a Subseqüência Comum Mais Longa de duas strings. Nesse caso, uma sequência será a original e a segunda será o inverso da sequência original.

O problema de Subseqüência Comum Mais Longa é como o problema de correspondência de padrões, exceto que você pode pular caracteres no texto. Além disso, o objetivo é retornar apenas uma partida, o maior tempo possível.

O LCS pode ser resolvido em usando Recursão e Memoização.O(n2)

Existe um algoritmo um pouco mais rápido descoberto por Masek e Paterson da complexidade de tempo . Artigo : Masek e PatersonO(n2/lgn)

Dois outros algoritmos apresentados por Hirschberg para calcular LCS de duas seqüências (tamanho ) e (tamanho ). Com base no pressuposto de que os símbolos que podem aparecer nessas seqüências de caracteres vêm de algum alfabeto de tamanho (isso é realmente verdade na maioria dos casos). Portanto, os símbolos podem ser armazenados na memória usando os bits , que caberão em uma palavra da memória. dois símbolos podem ser comparados no tempo . O número de diferentes na cadeia é indicado por , que é obviamente menor que e .AnBmtlog(t)O(1)Bsmt

  1. Este requer tempo em que é a duração do LCS. Isso é usado quando se espera que o comprimento do LCS seja pequeno. Quando resolvemos esse problema usando a Programação Dinâmica, descobrimos que a maioria das entradas na matriz é a mesma, para que possamos usar a idéia de Programação Dinâmica Esparsa.O(pn+nlgn)p

  2. Esse algoritmo requer tempo . Isso é muito eficiente quando o comprimento do LCS é próximo de , nesse caso, será próximo de .O(p(m+1p)logn)mO(nlgn)

Procedimentos e algoritmos detalhados são explicados no artigo de Hirschberg .

Um outro bom algoritmo é proposto por Sohel Rahman que é executado no tempo , em que é o número total de pares ordenados de posições nas quais as cadeias correspondem. Não é aplicável quando é a ordem de , mas há muitos casos em que é a ordem de . Este usa o conceito RMQ (Range Maximum Query). Artigo: RahmanO(Rloglogn)RRO(n2)Rn

Surendra
fonte
@FrankW, obrigado! Eu editei a resposta. Agora os links estão visíveis.
Surendra
Sua formatação ainda estava faltando; verifique minha edição para ver o que é possível. As referências do artigo ainda são ruins porque dependem do link sempre funcionando, para sempre. Veja aqui para obter conselhos; título, autores e ano devem ser indicados (pelo menos).
Raphael
Duas preocupações com o que você escreve: 1) "requer " não têm sentido (já que fornece limites superiores ) e ignorar que provavelmente está errado; Eu acho que eles mostram limites superiores dessas ordens, mas os algoritmos podem ser mais rápidos ainda. 2) Pelo menos no último parágrafo, você deseja . O()OΩ(n2)
Raphael
-1

Provavelmente estou perdendo alguma coisa, porque me parece bastante trivial: tente parear cada personagem com um personagem igual. Em seguida, coloque o primeiro caractere de cada par no lado esquerdo, o outro caractere no lado direito e, se houver algum caractere restante (ou seja, caracteres não emparelhados com outro), escolha um deles e coloque-o no meio.


fonte
1
Quando você tem (com palavras), como você decide se o primeiro e o último caractere do palíndromo devem ser ou ? Você precisa examinar o conteúdo de antes de tomar uma decisão se desejar ter o palíndromo mais longo. aubvawbu,v,wabu,v,w