Existe um algoritmo para verificar se uma string é uma catenação de palíndromos?

9

Existe um algoritmo de tempo linear para verificar se uma sequência de caracteres é uma concatenação de palíndromos? A única coisa que me vem à cabeça é a solução ingênua:

1. k = 1
2. Split string into k substrings (all possibilities) and check
3. k++
4. repeat

Nota: a resposta é trivialmente sim se as sequências de comprimento 1 forem definidas como palíndromos. Vamos supor que esse não seja o caso.

saadtaame
fonte
14
Se você estiver permitindo palíndromos triviais de comprimento 1 (por exemplo, a cadeia "a" é um palíndromo), todas as cadeias são concatenações de palíndromos.
Matt Lewis
É útil ou é um exercício?
Jan Hudec
@ MattLewis Você pode tentar minimizar o número de palíndromos. Jan, por que? Parece um bom exercício de programação dinâmica.
GD
1
@Haile No. Apenas palíndromos disjuntos.
Saadtaame
1
Norvig fez um extenso trabalho em Palindromes. Você pode estar interessado nesta página: norvig.com/palindrome.html
robowolverine

Respostas:

7

Supondo que você queira palíndromos separados, isso é conhecido como problema do PALSTAR e existe um algoritmo de tempo linear por Zvi Galil e Joel Seiferas. Um algoritmo de reconhecimento on-line em tempo linear para `` Palstar '' .

Você pode encontrar uma explicação do algoritmo no livro aqui: Algoritmos de texto (consulte a página vinculada e as páginas anteriores).

Se você concorda com um algoritmo de tempo quadrático, a programação dinâmica direta parece funcionar.

Dada uma string s[1,n], mantemos uma matriz nos dizendo se s[1,j] pode ser decomposto em palíndromos.

Também mantemos uma tabela 2D que nos diz se s[i,j]é um palíndromo ou não. Isso podemos construir emO(n2)escolhendo um centro e movendo dois ponteiros para fora, procurando palíndromos com esse centro. Faça isso para cada centro possível:Θ(n) centros, cada um O(n) Tempo.

Agora você pode conferir s[1,j+1] se pode ser decomposto em palíndromos, verificando cada 1ij1 se s[1,i] pode ser decomposto e se s[i+1,,j+1]é um palíndromo (usando a tabela 2D acima). Isso produz umΘ(n2) tempo e Θ(n2) algoritmo espacial.

O uso do espaço pode ser reduzido para O(n), se você usar o algoritmo on-line do Manacher para calcular se s[i+1,j+1] é um palíndromo (como i vai de j1 para 1), basicamente se livrando da tabela 2D.

Aryabhata
fonte
Isto é semelhante ao meu algoritmo, eu só não explicou a parte pré-processamento para deixá-lo como exercício para OP, mas eu não sei por que ninguém estava se preocupam com meu algoritmo :)
@SaeedAmiri: Você leu a primeira parte da minha resposta que menciona o tempo linear? Como é semelhante? Aliás, o OP mudou a pergunta para solicitar um algoritmo de tempo linear, o que torna sua resposta, e a segunda metade da minha resposta é irrelevante. Não excluí essa parte da minha resposta, porque queria mencionar o algoritmo de Manacher, que faz com que o algoritmo de programação dinâmica use apenas o espaço O (n) (e se livra da etapa de pré-processamento), e ainda pode ser relevante para outras pessoas que por acaso se deparar com esta pergunta
Aryabhata 28/04
Não leve a série, é brincadeira, eu gosto das suas respostas em geral, acho que há um problema com a minha escrita em inglês, porque o OP não entendeu minha solução e estava fora do meu humor desenhá-la por imagem . Mas o ponto bom do OP mudou sua pergunta recentemente, e pode haver uma solução semelhante ao algoritmo de Manacher (mas realmente não é fácil).
1
@SaeedAmiri: Eu vejo, não se preocupe então :-)
Aryabhata
3

Se a sobreposição for permitida, isso poderá ser feito em tempo linear (no tamanho da sequência de entrada).

Algumas definições

Vamos definir o conceito de palíndromo máximo :

Um palíndromo máximo de raio k de uma corda S é uma substring S 'tal que

  • começando do centro, S 'lê os mesmos k caracteres em ambas as direções
  • mas não para k + 1 caracteres
  • k> 1 (portanto, um único caractere não é um palíndromo)

por exemplo, se S = banana, então, S' = ananaé um palíndromo máximo de raio 2.

Um palíndromo máximo é um palíndromo máximo de raio k para alguns k.

Por exemplo, se S = banana, "ana", "anana", estão todas as suas palindromes máximas.

Usando palíndromos máximos

Agora, se pudéssemos localizar todos os palíndromos máximos de uma string , seria simples verificar se a string inteira é uma concatenação de palindromes.

Tome S = abbaccazayaz. Seus palíndromos máximos são:

  • abba, centrado entre as posições 2 e 3, raio = 2
  • acca, centralizado entre as posições 5 e 6, raio = 2
  • zayaz, centrado na posição 10, raio = 2

então "abba" se estende por [1..4], "acca" se estende por [4..7], "zayaz" se estende por [8..12]. Como a concatenação desses três palíndromos (a sobreposição é permitida?) Se estende por toda a cadeia, segue-se que "abbaccazayaz" é concatenação de palíndromos.

Computando palíndromos máximos em tempo linear

Agora, verifica-se que podemos localizar todos os palíndromos máximos de uma sequência S em tempo linear !*

A idéia é usar uma árvore de sufixos para S equipada com consultas de ancestrais comuns mais baixas em tempo constante .

Portanto, podemos verificar se uma string S de comprimento m é uma concatenação de palíndromos no tempo O (n).

* Gusfield, Dan (1997), "9.2 Encontrando todos os palíndromos máximos em tempo linear", Algoritmos em Strings, Árvores e Sequências

Haile
fonte
Supondo que os palíndromos sobrepostos sejam permitidos e que procuremos a menor seqüência do palíndromo, não vejo por que isso deve retornar a menor (embora não tenha um contra-exemplo). Se estamos verificando se é possível com palíndromos de raio pelo menosk, então é realmente útil. Além disso, nananão é um palíndromo, suponho que você quis dizer anana.
Khaur
Editado a coisa "anana", obrigado. Além disso, o OP não solicita uma sequência mínima de palíndromos: dado que um único caractere não é um palíndromo, basta decidir se a sequência de entrada é uma concatenação de palíndromos ou não.
Haile
1
Caracteres únicos são palíndromos (embora não sejam interessantes). Se você acha que não, então está resolvendo o segundo problema que cito parak=1. Em uma nota de complexidade, depois de calcular todos os palíndromos máximos, você ainda precisa verificar se eles abrangem toda a sequência, o que o IIRC leva tempo linear no número de palíndromos (que pode ser quase tão alto quanto o comprimento da sequência em casos patológicos) . De qualquer forma, acho que você deveria enfatizar mais que supõe que a sobreposição é permitida, pois não é uma suposição tão óbvia.
Khaur
1
@ Khaur Leva apenas um tempo linear de log se os intervalos não forem classificados. Nesse caso, eles provavelmente são.
Yuval Filmus
1
Nos comentários à pergunta, o OP acrescenta explicitamente que palíndromos sobrepostos não são permitidos. Portanto, esta solução na forma atual não é o que o OP está procurando. Penso que esta solução pode ser modificada para resolver também o caso não sobreposto, com alguma reflexão e máxima complexidade quadrática. Mas não pensei muito nisso.
Paresh
2

Suponha que o Palindrome [] [] seja uma matriz e o Palindrome (i, j) seja uma função que verifica se a subseqüência de i para j é palíndromo e retorna 1 se é palíndromo ou retorna infinito se não for palíndromo e você está procurando o menor número de partições, crie-a de baixo para cima:

Palindrome[i][i]=1.
0i<j<n:Palindrome[i][j]=min{Palindrome(i,j),minik<j{Palindrome[i,k]+Palindrome[i+1,k]}}

Você deve preencher células e cada célula recebe no máximo para que o algoritmo seja . Com uma pequena modificação (pré-processamento), você pode aprimorá-lo para . encontrar esta partição não é difícil.O(n2)O(n)O(n3)O(n2)


fonte
Você pode ilustrar com um exemplo? Diga:abbaaccaabba.
saadtaame
@ saadtaame, OK, aqui não é possível criar uma tabela (em cs.stackexchange), ou não consegui encontrar uma maneira de fazer isso, farei isso em algum lugar e colocarei a imagem aqui mais tarde. mas por enquanto você tenta entender por conta própria, comece com substrings de comprimento 1 e verifique palindroms de comprimento 2, .... e assim por diante.