Existe-t-il un algorithme pour vérifier si une chaîne est une caténation de palindromes?

9

Existe-t-il un algorithme à temps linéaire pour vérifier qu'une séquence de caractères est une concaténation de palindromes? La seule chose qui me vient à l'esprit est la solution naïve:

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

Remarque: la réponse est trivialement oui si les chaînes de longueur 1 sont définies comme des palindromes. Supposons que ce n'est pas le cas.

saadtaame
la source
14
Si vous autorisez des palindromes triviaux de longueur 1 (par exemple, la chaîne "a" est un palindrome), alors toutes les chaînes sont des concaténations de palindromes.
Matt Lewis
Est-ce utile ou un exercice?
Jan Hudec
@MattLewis Vous pouvez essayer de minimiser le nombre de palindromes. Jan, pourquoi? Cela ressemble à un bel exercice de programmation dynamique.
Pål GD
1
@Haile No. Palindromes disjoints uniquement.
saadtaame
1
Norvig a effectué un travail approfondi sur les palindromes. Vous pouvez être intéressé par cette page: norvig.com/palindrome.html
robowolverine

Réponses:

7

En supposant que vous vouliez des palindromes disjoints, cela est connu comme le problème PALSTAR, et il y a un algorithme de temps linéaire par Zvi Galil et Joel Seiferas. Un algorithme de reconnaissance en ligne en temps linéaire pour `` Palstar '' .

Vous pouvez trouver une explication de l'algorithme dans le livre ici: Text Algorithms (regardez la page liée et les pages précédentes).

Si vous êtes d'accord avec un algorithme de temps quadratique, la programmation dynamique directe semble fonctionner.

Étant donné une chaîne , nous maintenons un tableau nous indiquant si peut être décomposé en palindromes.s[1,n]s[1,j]

Nous maintenons également une table 2D qui nous indique si est un palindrome ou non. Nous pouvons construire cela en temps en choisissant un centre et en déplaçant deux pointeurs vers l'extérieur, en vérifiant les palindromes avec ce centre. Faites cela pour chaque centre possible: centres, chacun prenant fois.s[i,j]O(n2)Θ(n)O(n)

Maintenant, vous pouvez vérifier si peut être décomposé en palindromes, en vérifiant pour chaque si peut être décomposé, et si est un palindrome (en utilisant le tableau 2D ci-dessus). On obtient ainsi un temps et algorithme de l' espace.s[1,j+1]1ij1s[1,i]s[i+1,,j+1]Θ(n2)Θ(n2)

L'utilisation de l'espace peut être ramenée à , si vous utilisez l'algorithme en ligne de Manacher pour calculer si est un palindrome (comme passe de à ) , se débarrassant essentiellement de la table 2D.O(n)s[i+1,j+1]ij11

Aryabhata
la source
Ceci est similaire à mon algorithme, je n'ai tout simplement pas expliqué la partie de prétraitement pour la laisser comme exercice à OP, mais je ne sais pas pourquoi personne ne se souciait de mon algorithme :)
@SaeedAmiri: Avez-vous lu la première partie de ma réponse qui mentionne le temps linéaire? En quoi est-il similaire? btw, OP a changé la question pour demander un algorithme de temps linéaire, ce qui rend votre réponse, et la seconde moitié de ma réponse non pertinente. Je n'ai pas supprimé cette partie de ma réponse, car je voulais mentionner l'algorithme de Manacher qui fait que l'algorithme de programmation dynamique n'utilise que l'espace O (n) (et se débarrasse de l'étape de prétraitement), et il pourrait toujours être pertinent pour d'autres personnes qui arriver à rencontrer cette question
Aryabhata
Ne le prenez pas en série, c'est juste une blague, j'aime vos réponses en général, je pense qu'il y a un problème avec mon écriture en anglais, parce que OP n'a pas compris ma solution, et il était hors de mon humeur de la dessiner par l'image . Mais bon point OP a changé sa question récemment, et il y a peut-être une solution similaire à l'algorithme de Manacher (mais ce n'est vraiment pas facile).
1
@SaeedAmiri: Je vois, pas de soucis alors :-)
Aryabhata
3

Si le chevauchement est autorisé, cela peut être fait en temps linéaire (dans la taille de la chaîne d'entrée).

Quelques définitions

Définissons le concept de palindrome maximal :

Un palindrome maximal de rayon k d'une chaîne S est une sous-chaîne S 'telle que

  • à partir du centre, S 'lit les mêmes k caractères dans les deux sens
  • mais pas pour k + 1 caractères
  • k> 1 (donc un seul caractère n'est pas un palindrome)

par exemple, si S = banana, alors S' = ananaest un palindrome maximal de rayon 2.

Un palindrome maximal est un palindrome maximal de rayon k pour certains k.

Par exemple, si S = banana, "ana", "anana", sont tous ses palindromes maximale.

Utilisation de palindromes maximaux

Maintenant, si nous pouvions localiser tous les palindromes maximaux d'une chaîne , il serait simple de vérifier si la chaîne entière est une concaténation de palindromes.

Prenez S = abbaccazayaz. Ses palindromes maximaux sont:

  • abba, centré entre la position 2 et 3, rayon = 2
  • acca, centré entre la position 5 et 6, rayon = 2
  • zayaz, centré en position 10, rayon = 2

donc "abba" s'étend sur [1..4], "acca" s'étend sur [4..7], "zayaz" s'étend sur [8..12]. Puisque la concaténation de ces trois palindromes (le chevauchement est autorisé?) S'étend sur toute la chaîne, il s'ensuit que "abbaccazayaz" est la concaténation des palindromes.

Calcul des palindromes maximaux en temps linéaire

Maintenant, il s'avère que nous pouvons localiser tous les palindromes maximaux d'une chaîne S en temps linéaire !*

L'idée est d'utiliser un arbre de suffixes pour S équipé de requêtes d'ancêtres communs à temps constant .

On peut donc vérifier si une chaîne S de longueur m est une concaténation de palindromes en temps O (n).

* Gusfield, Dan (1997), "9.2 Trouver tous les palindromes maximaux en temps linéaire", Algorithmes sur les chaînes, les arbres et les séquences

Haile
la source
En supposant que les palindromes qui se chevauchent sont autorisés et que nous recherchons la plus petite séquence de palindrome, je ne vois pas pourquoi cela devrait renvoyer le plus petit (je n'ai cependant pas de contre-exemple). Si nous vérifions si cela est possible avec des palindromes de rayon au moinsk, alors c'est effectivement utile. De plus, ce nanan'est pas un palindrome, je suppose que vous vouliez dire à la ananaplace.
Khaur
Modifié la chose "anana", merci. De plus, OP ne demande pas de séquence de palindromes minimale: étant donné qu'un seul caractère n'est pas un palindrome, il suffit de décider si la chaîne d'entrée est une concaténation de palindromes ou non.
Haile
1
Les personnages uniques sont des palindromes (quoique sans intérêt). Si vous supposez qu'ils ne le sont pas, vous résolvez le deuxième problème que je mentionne pourk=1. Sur une note de complexité, après avoir calculé tous les palindromes maximaux, vous devez toujours vérifier qu'ils couvrent toute la séquence, ce qui demande à l'IIRC un temps log-linéaire dans le nombre de palindromes (qui peut être presque aussi élevé que la longueur de la séquence dans les cas pathologiques) . Quoi qu'il en soit, je pense que vous devriez souligner davantage que vous supposez que le chevauchement est autorisé, car ce n'est pas une hypothèse aussi évidente.
Khaur
1
@Khaur Cela ne prend du temps log-linéaire que si les intervalles ne sont pas triés. Dans ce cas, ils le sont probablement.
Yuval Filmus
1
Dans les commentaires à la question, le PO ajoute explicitement que les palindromes qui se chevauchent ne sont pas autorisés. Donc, cette solution sous sa forme actuelle n'est pas ce que le PO recherche. Je pense que cette solution peut également être modifiée pour résoudre le cas de non-chevauchement, avec une certaine réflexion et une complexité presque quadratique. Mais je n'y ai pas beaucoup réfléchi.
Paresh
2

Supposons que Palindrome [] [] est un tableau et Palindrome (i, j) est une fonction qui vérifie si la sous-chaîne de i à j est palindrome et renvoie 1 si est palindrome ou renvoie l'infini si ce n'est pas palindrome, et si vous recherchez le plus petit nombre de partitions, créez-le de bas en haut:

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

Vous devez remplir cellules et chaque cellule prend au plus donc l'algorithme est , avec une petite modification (prétraitement) vous pouvez l'améliorer en , aussi trouver cette partition n'est pas difficile.O(n2)O(n)O(n3)O(n2)


la source
Pouvez-vous illustrer avec un exemple? Dire:abbaaccaabba.
saadtaame
@saadtaame, OK, il n'est pas possible de créer une table (dans cs.stackexchange), ou je n'ai pas trouvé de moyen de le faire, je le ferai quelque part et je mettrai l'image ici plus tard. mais pour l'instant vous essayez de le comprendre vous-même, commencez par des sous-chaînes de longueur 1, puis vérifiez les palindromes de longueur 2, .... et ainsi de suite.