Ecrire une fonction qui renvoie le palindrome le plus long dans une chaîne donnée


102

par exemple "ccddcc" dans la chaîne "abaccddccefe"

J'ai pensé à une solution mais elle fonctionne en temps O (n ^ 2)

Algo 1:

Étapes: c'est une méthode de force brute

  1. Avoir 2 boucles
    for pour i = 1 à i inférieur à array.length -1
    pour j = i + 1 à j inférieur à array.length
  2. De cette façon, vous pouvez obtenir une sous-chaîne de toutes les combinaisons possibles à partir du tableau
  3. Avoir une fonction palindrome qui vérifie si une corde est palindrome
  4. donc pour chaque sous-chaîne (i, j) appelez cette fonction, s'il s'agit d'un palindrome, stockez-la dans une variable chaîne
  5. Si vous trouvez la sous-chaîne palindrome suivante et si elle est supérieure à la sous-chaîne actuelle, remplacez-la par la sous-chaîne actuelle.
  6. Enfin votre variable chaîne aura la réponse

Problèmes: 1. Cet algorithme s'exécute en temps O (n ^ 2).

Algo 2:

  1. Inversez la chaîne et stockez-la dans un tableau différent
  2. Recherchez maintenant la plus grande sous-chaîne correspondante entre le tableau
  3. Mais cela fonctionne aussi en temps O (n ^ 2)

Pouvez-vous penser à un algo qui fonctionne dans un meilleur temps. Si possible O (n) fois


42
Je pense que le premier est O(n^2)d'obtenir les sous-chaînes * O(n)pour vérifier si ce sont des palindromes, pour un total de O(n^3)?
Skylar Saveland

Et si je savais que je travaillais avec palindrome et que je sauvegardais mes chaînes en deux moitiés, puis si j'utilisais Java, j'aurais O (1) vérifier la fonction?
viki.omega9

10
Le secong algo est-il correct? Qu'en est-il de la chaîne: "abcdecba". La plus grande sous-chaîne correspondante est ("abcdecba" vs "abcedcba"): "abc" ou "cba". Cependant, les deux ne sont pas des palindromes.
Yarneo

@Learner, juste curieux, dans vos étapes au-dessus de quel tableau vous référez-vous dans vos boucles for? Par tableau, faites-vous référence à la chaîne? Longueur de chaine?
Zolt

1
pour ceux qui cherchent une réponse avec O (n ^ 2) - geeksforgeeks.org/longest-palindrome-substring-set-1
Shirish Herwade

Réponses:


76

Vous pouvez trouver le plus long palindrome en utilisant l'algorithme de Manacher dans le O(n)temps! Sa mise en œuvre peut être trouvée ici et ici .

Pour l'entrée, String s = "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE"il trouve la sortie correcte qui est 1234567887654321.


3
Je ne comprends pas en quoi c'est linéaire. Je vois un whileintégré dans le foravec une délimitation qui semble similaire à la boucle externe.
v.oddou du


9

L'Algo 2 peut ne pas fonctionner pour toutes les cordes. Voici un exemple d'une telle chaîne "ABCDEFCBA".

Non pas que la chaîne ait "ABC" et "CBA" comme sous-chaîne. Si vous inversez la chaîne d'origine, ce sera "ABCFEDCBA". et la plus longue sous-chaîne correspondante est "ABC" qui n'est pas un palindrome.

Vous devrez peut-être vérifier en plus si cette sous-chaîne correspondante la plus longue est en fait un palindrome dont le temps d'exécution est O (n ^ 3).


2
Il est important de noter qu'Algo 2 devrait fonctionner pour le "palindrome de sous-séquence correspondant le plus long" qui est un problème d'algorithmes courant où les caractères de sous-séquence peuvent également être séparés dans la chaîne. Par exemple, la plus longue sous-séquence correspondante (y compris les séparations de caractères) entre les deux chaînes ci-dessus est "ABCFCBA" qui est aussi un palindrome :) Voici un lien décrivant le problème LCS: ics.uci.edu/~eppstein/161/960229.html
Jake Drew

5

Pour autant que j'ai compris le problème, nous pouvons trouver des palindromes autour d'un index central et étendre notre recherche dans les deux sens, à droite et à gauche du centre. Compte tenu de cela et sachant qu'il n'y a pas de palindrome aux coins de l'entrée, nous pouvons définir les limites à 1 et longueur-1. Tout en faisant attention aux limites minimum et maximum de la chaîne, nous vérifions si les caractères aux positions des index symétriques (droite et gauche) sont les mêmes pour chaque position centrale jusqu'à ce que nous atteignions notre centre de limite supérieure maximum.

La boucle externe est O (n) (max n-2 itérations), et la boucle while interne est O (n) (max autour de (n / 2) - 1 itérations)

Voici mon implémentation Java en utilisant l'exemple fourni par d'autres utilisateurs.

class LongestPalindrome {

    /**
     * @param input is a String input
     * @return The longest palindrome found in the given input.
     */
    public static String getLongestPalindrome(final String input) {
        int rightIndex = 0, leftIndex = 0;
        String currentPalindrome = "", longestPalindrome = "";
        for (int centerIndex = 1; centerIndex < input.length() - 1; centerIndex++) {
            leftIndex = centerIndex - 1;  rightIndex = centerIndex + 1;
            while (leftIndex >= 0 && rightIndex < input.length()) {
                if (input.charAt(leftIndex) != input.charAt(rightIndex)) {
                    break;
                }
                currentPalindrome = input.substring(leftIndex, rightIndex + 1);
                longestPalindrome = currentPalindrome.length() > longestPalindrome.length() ? currentPalindrome : longestPalindrome;
                leftIndex--;  rightIndex++;
            }
        }
        return longestPalindrome;
    }

    public static void main(String ... args) {
        String str = "HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE";
        String longestPali = getLongestPalindrome(str);
        System.out.println("String: " + str);
        System.out.println("Longest Palindrome: " + longestPali);
    }
}

Le résultat de ceci est le suivant:

marcello:datastructures marcello$ javac LongestPalindrome
marcello:datastructures marcello$ java LongestPalindrome
String: HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE
Longest Palindrome: 12345678987654321

6
Si je donne "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE" Cela ne fonctionne pas mais la réponse devrait être 1234567887654321
Elbek

1
@j_random_hacker non, c'est l'une des solutions quadratiques. C'est couvert ici comme expandAroundCenter.
v.oddou le

@ v.oddou: Vous avez tout à fait raison, et je ne sais pas comment j'ai conclu O (n ^ 3) étant donné qu'il n'y a que 2 boucles imbriquées! Je vais supprimer ce commentaire erroné ... Mais j'ai également remarqué que cette solution a un problème, que je vais mettre dans un commentaire séparé afin que l'auteur le remarque, espérons-le.
j_random_hacker

Ma revendication précédente de la complexité du temps O (n ^ 3) était erronée (merci @ v.oddou pour l'avoir signalé!) Mais il y a un autre problème: ce code ne considère pas les palindromes de même longueur. Cela pourrait être corrigé en ajoutant une deuxième boucle externe très similaire (également O (n ^ 2) pour ne pas affecter la complexité temporelle O (n ^ 2)) qui étend les palindromes autour de chacune des n-1 positions entre chaque paire de caractères. +2 si vous corrigez :)
j_random_hacker

2

avec regex et ruby, vous pouvez rechercher des palindromes courts comme ceci:

PROMPT> irb
>> s = "longtextwithranynarpalindrome"
=> "longtextwithranynarpalindrome"
>> s =~ /((\w)(\w)(\w)(\w)(\w)\6\5\4\3\2)/; p $1
nil
=> nil
>> s =~ /((\w)(\w)(\w)(\w)\w\5\4\3\2)/; p $1
nil
=> nil
>> s =~ /((\w)(\w)(\w)(\w)\5\4\3\2)/; p $1
nil
=> nil
>> s =~ /((\w)(\w)(\w)\w\4\3\2)/; p $1
"ranynar"
=> nil

2

J'ai écrit le programme Java suivant par curiosité, HTH simple et explicite. Merci.

/**
 *
 * @author sanhn
 */
public class CheckPalindrome {

    private static String max_string = "";

    public static void checkSubString(String s){
        System.out.println("Got string is "+s);
        for(int i=1;i<=s.length();i++){
            StringBuilder s1 = new StringBuilder(s.substring(0,i));
            StringBuilder s2 = new StringBuilder(s.substring(0,i));
            s2.reverse();
            if(s1.toString().equals(s2.toString())){
                if(max_string.length()<=s1.length()){
                    max_string = s1.toString();
                    System.out.println("tmp max is "+max_string);
                }

            }
        }
    }

    public static void main(String[] args){
        String s="HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE";

        for(int i=0; i<s.length(); i++)
            checkSubString(s.substring(i, s.length()));

        System.out.println("Max string is "+max_string);
    }
}

1

On m'a posé cette question récemment. Voici la solution que j'ai [finalement] trouvée. Je l'ai fait en JavaScript car c'est assez simple dans ce langage.

Le concept de base est que vous parcourez la chaîne à la recherche du plus petit palindrome à plusieurs caractères possible (un à deux ou trois caractères). Une fois que vous avez cela, élargissez les frontières des deux côtés jusqu'à ce qu'il cesse d'être un palindrome. Si cette longueur est plus longue que la plus longue actuelle, enregistrez-la et avancez.

// This does the expanding bit.
function getsize(s, start, end) {
    var count = 0, i, j;
    for (i = start, j = end; i >= 0 && j < s.length; i--, j++) {
        if (s[i] !== s[j]) {
            return count;
        }
        count = j - i + 1; // keeps track of how big the palindrome is
    }
    return count;
}

function getBiggestPalindrome(s) {
    // test for simple cases
    if (s === null || s === '') { return 0; }
    if (s.length === 1) { return 1; }
    var longest = 1;
    for (var i = 0; i < s.length - 1; i++) {
        var c = s[i]; // the current letter
        var l; // length of the palindrome
        if (s[i] === s[i+1]) { // this is a 2 letter palindrome
            l = getsize(s, i, i+1);
        }
        if (i+2 < s.length && s[i] === s[i+2]) { // 3 letter palindrome
            l = getsize(s, i+1, i+1);
        }
        if (l > longest) { longest = l; }
    }
    return longest;
}

Cela pourrait certainement être nettoyé et optimisé un peu plus, mais il devrait avoir de très bonnes performances dans tous les scénarios sauf dans le pire des cas (une chaîne de la même lettre).


1
À l'origine, je pensais que l'algo n ° 1 de l'OP était le temps O (n ^ 2), mais il s'agit en fait d'un O (n ^ 3), donc même si votre algorithme ne parvient pas à atteindre la limite réalisable O (n), c'est toujours une amélioration.
j_random_hacker

1
vous appelez cela «simple», mais c'est plein de i j l s ifmaintenance. multi return points, edge cases ...
v.oddou

1

Salut Voici mon code pour trouver le palindrome le plus long de la chaîne. Veuillez vous référer au lien suivant pour comprendre l'algorithme http://stevekrenzel.com/articles/longest-palnidrome

Les données de test utilisées sont HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE

 //Function GetPalindromeString

public static string GetPalindromeString(string theInputString)
 { 

        int j = 0;
        int k = 0;
        string aPalindrome = string.Empty;
        string aLongestPalindrome = string.Empty ;          
        for (int i = 1; i < theInputString.Length; i++)
        {
            k = i + 1;
            j = i - 1;
            while (j >= 0 && k < theInputString.Length)
            {
                if (theInputString[j] != theInputString[k])
                {
                    break;
                }
                else
                {
                    j--;
                    k++;
                }
                aPalindrome = theInputString.Substring(j + 1, k - j - 1);
                if (aPalindrome.Length > aLongestPalindrome.Length)
                {
                    aLongestPalindrome = aPalindrome;
                }
            }
        }
        return aLongestPalindrome;     
  }

Je ne sais pas si cela fonctionne avec des palindromes de même longueur ... pouvez-vous confirmer?
st0le

Cela fonctionne même pour les palindromes, vous pouvez exécuter ce programme et me faire savoir si cela ne fonctionne pas pour vous.Pour la compréhension de l'algorithme, veuillez consulter le lien suivant stevekrenzel.com/articles/longest-palnidrome
Mohit Bhandari

@ st0le: Cette logique ne fonctionnera même pas pour les palindromes, mais elle pourrait être ajustée même pour les palindromes.
Mohit Bhandari

jamais lu votre commentaire précédent jusqu'à aujourd'hui ... vous ne m'avez pas parlé la dernière fois ... prenez votre temps, c'était juste une observation.
st0le

2
À l'origine, je pensais que l'algo n ° 1 de l'OP était le temps O (n ^ 2), mais il s'agit en fait d'un O (n ^ 3), donc même si votre algorithme ne parvient pas à atteindre la limite réalisable O (n), c'est toujours une amélioration.
j_random_hacker

1

Voir l'article de Wikipédia sur ce sujet. Exemple d' implémentation Java de l' algorithme de Manacher pour la solution linéaire O (n) de l'article ci-dessous:

import java.util.Arrays; public class ManachersAlgorithm {chaîne statique publique findLongestPalindrome (String s) {if (s == null || s.length () == 0) return "";

char[] s2 = addBoundaries(s.toCharArray());
int[] p = new int[s2.length]; 
int c = 0, r = 0; // Here the first element in s2 has been processed.
int m = 0, n = 0; // The walking indices to compare if two elements are the same
for (int i = 1; i<s2.length; i++) {
  if (i>r) {
    p[i] = 0; m = i-1; n = i+1;
  } else {
    int i2 = c*2-i;
    if (p[i2]<(r-i)) {
      p[i] = p[i2];
      m = -1; // This signals bypassing the while loop below. 
    } else {
      p[i] = r-i;
      n = r+1; m = i*2-n;
    }
  }
  while (m>=0 && n<s2.length && s2[m]==s2[n]) {
    p[i]++; m--; n++;
  }
  if ((i+p[i])>r) {
    c = i; r = i+p[i];
  }
}
int len = 0; c = 0;
for (int i = 1; i<s2.length; i++) {
  if (len<p[i]) {
    len = p[i]; c = i;
  }
}
char[] ss = Arrays.copyOfRange(s2, c-len, c+len+1);
return String.valueOf(removeBoundaries(ss));   }
private static char[] addBoundaries(char[] cs) {
if (cs==null || cs.length==0)
  return "||".toCharArray();

char[] cs2 = new char[cs.length*2+1];
for (int i = 0; i<(cs2.length-1); i = i+2) {
  cs2[i] = '|';
  cs2[i+1] = cs[i/2];
}
cs2[cs2.length-1] = '|';
return cs2;   }
private static char[] removeBoundaries(char[] cs) {
if (cs==null || cs.length<3)
  return "".toCharArray();

char[] cs2 = new char[(cs.length-1)/2];
for (int i = 0; i<cs2.length; i++) {
  cs2[i] = cs[i*2+1];
}
return cs2;   }     }

1

Une Regexpsolution efficace qui évite la force brute

Commence par toute la longueur de la chaîne et fonctionne vers le bas jusqu'à 2 caractères, existe dès qu'une correspondance est faite

Pour "abaccddccefe"les tests d'expression régulière, 7 correspondances avant de revenir ccddcc.

(.) (.) (.) (.) (.) (.) (\ 6) (\ 5) (\ 4) (\ 3) (\ 2) (\ 1)
(.) (.) (. ) (.) (.) (.) (\ 5) (\ 4) (\ 3) (\ 2) (\ 1)
(.) (.) (.) (.) (.) (\ 5) ( \ 4) (\ 3) (\ 2) (\ 1)
(.) (.) (.) (.) (.) (\ 4) (\ 3) (\ 2) (\ 1)
(.) ( .) (.) (.) (\ 4) (\ 3) (\ 2) (\ 1)
(.) (.) (.) (.) (\ 3) (\ 2) (\ 1)
(. ) (.) (.) (\ 3) (\ 2) (\ 1)

Dim strTest
wscript.echo Palindrome("abaccddccefe")

Sub Test()
Dim strTest
MsgBox Palindrome("abaccddccefe")
End Sub

fonction

Function Palindrome(strIn)

Set objRegex = CreateObject("vbscript.regexp")

For lngCnt1 = Len(strIn) To 2 Step -1
    lngCnt = lngCnt1 \ 2
    strPal = vbNullString

    For lngCnt2 = lngCnt To 1 Step -1
        strPal = strPal & "(\" & lngCnt2 & ")"
    Next

    If lngCnt1 Mod 2 = 1 Then strPal = "(.)" & strPal

    With objRegex
        .Pattern = Replace(Space(lngCnt), Chr(32), "(.)") & strPal
        If .Test(strIn) Then
            Palindrome = .Execute(strIn)(0)
            Exit For
        End If
    End With
Next

End Function

@DickKusleika pouvez-vous mettre à jour mon commentaire sur dailydoseofexcel.com/archives/2016/01/14/… avec le code révisé ci-dessus. Thx
brettdj

1
public static void main(String[] args) {
         System.out.println(longestPalindromeString("9912333321456")); 
}

    static public String intermediatePalindrome(String s, int left, int right) {
        if (left > right) return null;
        while (left >= 0 && right < s.length()
                && s.charAt(left) == s.charAt(right)) {
            left--;
            right++;
        }
        return s.substring(left + 1, right);
    }


    public static String longestPalindromeString(String s) {
        if (s == null) return null;
        String longest = s.substring(0, 1);
        for (int i = 0; i < s.length() - 1; i++) {
            //odd cases like 121
            String palindrome = intermediatePalindrome(s, i, i);
            if (palindrome.length() > longest.length()) {
                longest = palindrome;
            }
            //even cases like 1221
            palindrome = intermediatePalindrome(s, i, i + 1);
            if (palindrome.length() > longest.length()) {
                longest = palindrome;
            }
        }
        return longest;
    }

0

Essayez la chaîne - "HYTBCABADEFGHABCDEDCBAGHTFYW123456789987654321ZWETYGDE"; Cela devrait fonctionner pour les copains pairs et impairs. Un grand merci à Mohit!

en utilisant l'espace de noms std;

string largestPal(string input_str)
{
  string isPal = "";
  string largest = "";
  int j, k;
  for(int i = 0; i < input_str.length() - 1; ++i)
    {
      k = i + 1;
      j = i - 1;

      // starting a new interation                                                      
      // check to see if even pal                                                       
      if(j >= 0 && k < input_str.length()) {
        if(input_str[i] == input_str[j])
          j--;
        else if(input_str[i] == input_str[j]) {
          k++;
        }
      }
      while(j >= 0 && k < input_str.length())
        {
          if(input_str[j] != input_str[k])
            break;
          else
            {
              j--;
              k++;
            }
          isPal = input_str.substr(j + 1, k - j - 1);
            if(isPal.length() > largest.length()) {
              largest = isPal;
            }
        }
    }
  return largest;
}

2
Cela fait presque les choses en temps O (n ^ 2). Pourquoi construire isPal- une opération O (n) - uniquement pour mesurer sa longueur !? Il a également une tentative de buggy pour gérer même les palindromes. Sur la bugginess même-palindrome: else if(input_str[i] == input_str[j])ne peut jamais réussir parce que ce même test doit avoir échoué dans la ifdéclaration précédente ; et c'est bogué de toute façon parce que vous ne pouvez pas dire simplement en regardant 2 caractères espacés de 2 positions si vous regardez un palindrome pair ou impair (considérez AAAet AAAA).
j_random_hacker

0

Le code suivant calcule Palidrom pour les chaînes de longueur paire et impaire.

Ce n'est pas la meilleure solution mais fonctionne pour les deux cas

HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE

private static String getLongestPalindrome(String string) {
    String odd = getLongestPalindromeOdd(string);
    String even = getLongestPalindromeEven(string);
    return (odd.length() > even.length() ? odd : even);
}

public static String getLongestPalindromeOdd(final String input) {
    int rightIndex = 0, leftIndex = 0;
    String currentPalindrome = "", longestPalindrome = "";
    for (int centerIndex = 1; centerIndex < input.length() - 1; centerIndex++) {
        leftIndex = centerIndex;
        rightIndex = centerIndex + 1;
        while (leftIndex >= 0 && rightIndex < input.length()) {
            if (input.charAt(leftIndex) != input.charAt(rightIndex)) {
                break;
            }
            currentPalindrome = input.substring(leftIndex, rightIndex + 1);
            longestPalindrome = currentPalindrome.length() > longestPalindrome
                    .length() ? currentPalindrome : longestPalindrome;
            leftIndex--;
            rightIndex++;
        }
    }
    return longestPalindrome;
}

public static String getLongestPalindromeEven(final String input) {
    int rightIndex = 0, leftIndex = 0;
    String currentPalindrome = "", longestPalindrome = "";
    for (int centerIndex = 1; centerIndex < input.length() - 1; centerIndex++) {
        leftIndex = centerIndex - 1;
        rightIndex = centerIndex + 1;
        while (leftIndex >= 0 && rightIndex < input.length()) {
            if (input.charAt(leftIndex) != input.charAt(rightIndex)) {
                break;
            }
            currentPalindrome = input.substring(leftIndex, rightIndex + 1);
            longestPalindrome = currentPalindrome.length() > longestPalindrome
                    .length() ? currentPalindrome : longestPalindrome;
            leftIndex--;
            rightIndex++;
        }
    }
    return longestPalindrome;
}

0
  1. Modifiez la chaîne pour séparer chaque caractère à l'aide d'un séparateur [cela permet d'incorporer des palindromes pairs et impairs]
  2. Trouvez des palindromes autour de chaque personnage en le traitant comme un centre

Nous pouvons trouver tous les palindromes de toute longueur en utilisant ceci.

Échantillon :

mot = abcdcbc

modifiedString = a # b # c # d # c # b # c

palinCount = 1010105010301

longueur du palindrome le plus long = 5;

palindrome le plus long = bcdcb

classe publique MyLongestPalindrome {

static String word;
static int wordlength;
static int highestcount = 0;
static int newlength;
static char[] modifiedString; // stores modified string
static int[] palinCount; // stores palindrome length at each position
static char pound = '#';

public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub
    System.out.println("Enter String : ");
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader bfr = new BufferedReader(isr);
    word = bfr.readLine();
    wordlength = word.length();
    newlength = (wordlength * 2) - 1;
    convert();
    findpalindrome();
    display();
}

// Inserting # in string
public static void convert() {

    modifiedString = new char[newlength];
    int j = 0;
    int i;
    for (i = 0; i < wordlength - 1; i++) {
        modifiedString[j++] = word.charAt(i);
        modifiedString[j++] = pound;
    }
    modifiedString[j] = word.charAt(i);
}

// display all palindromes of highest length
public static void display() {
    String palindrome;
    String s = new String(modifiedString);
    System.out.println("Length of longest palindrome = " + highestcount);
    for (int i = 0; i < newlength; i++) {
        if (palinCount[i] == highestcount) {
            palindrome = s.substring(i - (highestcount - 1), i
                    + (highestcount));
            i = i + (highestcount - 1);
            palindrome = palindrome.replace("#", "");
            System.out.println(palindrome);
        }
    }
}

// populate palinCount with length of palindrome string at each position
public static void findpalindrome() {
    int left, right, count;
    palinCount = new int[newlength];
    palinCount[0] = 1;
    palinCount[newlength - 1] = 1;
    for (int i = 1; i < newlength - 1; i++) {
        count = 0;
        left = i - 1;
        right = i + 1;
        ;
        if (modifiedString[i] != pound)
            count++;
        while (left >= 0 && right < newlength) {
            if (modifiedString[left] == modifiedString[right]) {
                if (modifiedString[left] != pound)
                    count = count + 2;
                left--;
                right++;
            } else
                break;
        }

        palinCount[i] = count;
        highestcount = count > highestcount ? count : highestcount;

    }

}

}


0

Cela retournera la plus longue chaîne de palindrome de la chaîne donnée

-(BOOL)isPalindromString:(NSString *)strInput
{
    if(strInput.length<=1){
        return NO;
    }
    int halfLenth = (int)strInput.length/2;

    BOOL isPalindrom = YES;
    for(NSInteger i=0; i<halfLenth; i++){

        char a = [strInput characterAtIndex:i];
        char b = [strInput characterAtIndex:(strInput.length-1)-i];

        if(a != b){
            isPalindrom = NO;
            break;
        }
    }
    NSLog(@"-%@- IS Plaindrom %@",strInput,(isPalindrom ? @"YES" : @"NO"));
    return isPalindrom;
}


-(NSString *)longestPalindrom:(NSString *)strInput
{
    if(strInput.length<=1){
        return @"";
    }

    NSString *strMaxPalindrom = @"";

    for(int i = 0; i<strInput.length ; i++){

        for(int j = i; j<strInput.length ; j++){

            NSString *strSub = [strInput substringWithRange:NSMakeRange(i, strInput.length-j)];

            if([self isPalindromString:strSub]){

                if(strSub.length>strMaxPalindrom.length){

                    strMaxPalindrom = strSub;
                }
            }
        }
    }
    NSLog(@"-Max - %@",strMaxPalindrom);
    return strMaxPalindrom;
}

-(void)test
{
    [self longestPalindrom:@"abcccbadeed"];
}

== SORTIE ===

Entrée: abcccde Sortie: ccc

Entrée: abcccbd Sortie: bcccb

Entrée: abedccde Sortie: edccde

Entrée: abcccdeed Sortie: acte

Entrée: abcccbadeed Sortie: abcccba


0

Voici une implémentation en javascript:

var longestPalindromeLength = 0;
var longestPalindrome = ''

function isThisAPalidrome(word){
  var reverse = word.split('').reverse().join('')
  return word == reverse
}

function findTheLongest(word){ // takes a word of your choice
  for(var i = 0; i < word.length; i++){ // iterates over each character
    var wordMinusOneFromBeginning = word.substr(i, word.length) // for each letter, create the word minus the first char
    for(var j = wordMinusOneFromBeginning.length; j > 0; j--){ // for the length of the word minus the first char
      var wordMinusOneFromEnding = wordMinusOneFromBeginning.substr(0, j) // create a word minus the end character
      if(wordMinusOneFromEnding <= 0) // make sure the value is more that 0,
      continue // if more than zero, proced to next if statement
      if(isThisAPalidrome(wordMinusOneFromEnding)){ // check if the word minus the first character, minus the last character = a plaindorme
        if(wordMinusOneFromEnding.length > longestPalindromeLength){ // if it is
          longestPalindromeLength = wordMinusOneFromEnding.length; // save its length
          longestPalindrome = wordMinusOneFromEnding // and save the string itself
        } // exit the statement that updates the longest palidrome
      } // exit the stament that checks for a palidrome
    } // exit the loop that goes backwards and takes a letter off the ending
  } // exit the loop that goes forward and takes off the beginning letter
  return console.log('heres the longest string: ' + longestPalindrome
  + ' its ' + longestPalindromeLength + ' charachters in length'); // return the longest palidrome! :)
}
findTheLongest('bananas');


Je ne sais pas pourquoi cela a été voté à la baisse - cela fonctionne comme un charme. M'a fait passer une interview avec les technologies CA très bien.
alex bennett le

0

Pour une solution linéaire, vous pouvez utiliser l'algorithme de Manacher. Il existe un autre algorithme appelé Algorithme de Gusfield, et ci-dessous le code en java:

public class Solution {  
    char[] temp;   
    public int match(int a, int b,int len){   
        int i = 0;   
        while (a-i>=0 && b+i<len && temp[a-i] == temp[b+i]) i++;   
        return i;   
    }  

    public String longestPalindrome(String s) {  

        //This makes use of the assumption that the string has not more than 1000 characters.  
        temp=new char[1001*2];  
        int[] z=new int[1001 * 2];  
        int L=0, R=0;  
        int len=s.length();  

        for(int i=0;i<len*2+1;i++){  
            temp[i]='.';  
        }  

        for(int i=0;i<len;++i){  
            temp[i*2+1] = s.charAt(i);  
        }  

        z[0]=1;  
        len=len*2+1;  

        for(int i=0;i<len;i++){  
            int ii = L - (i - L);     
            int n = R + 1 - i;  
            if (i > R)  
            {  
                z[i] = match(i, i,len);  
                L = i;  
                R = i + z[i] - 1;  
            }  
            else if (z[ii] == n)  
            {  
                z[i] = n + match(i-n, i+n,len);  
                L = i;  
                R = i + z[i] - 1;  
            }  
            else  
            {  
                z[i] = (z[ii]<= n)? z[ii]:n;  
            }   
        }  

        int n = 0, p = 0;  
        for (int i=0; i<len; ++i)  
            if (z[i] > n)  
                n = z[p = i];  

        StringBuilder result=new StringBuilder();  
        for (int i=p-z[p]+1; i<=p+z[p]-1; ++i)  
            if(temp[i]!='.')  
                result.append(String.valueOf(temp[i]));  

        return result.toString();  
    }  
}  

Vous pouvez en savoir plus sur d'autres solutions telles que la meilleure solution O (n ^ 2) ou l'algorithme de Manacher sur mon propre blog .


0

Ici, j'ai écrit une logique, essayez-le :)

public class palindromeClass{

public  static String longestPalindromeString(String in) {
        char[] input = in.toCharArray();
        int longestPalindromeStart = 0;
        int longestPalindromeEnd = 0;

        for (int mid = 0; mid < input.length; mid++) {
            // for odd palindrome case like 14341, 3 will be the mid
            int left = mid-1;
            int right = mid+1;
            // we need to move in the left and right side by 1 place till they reach the end
            while (left >= 0 && right < input.length) {
                // below check to find out if its a palindrome
                if (input[left] == input[right]) {
                    // update global indexes only if this is the longest one till now
                    if (right - left > longestPalindromeEnd
                            - longestPalindromeStart) {
                        longestPalindromeStart = left;
                        longestPalindromeEnd = right;
                    }
                }
                else
                    break;
                left--;
                right++;
            }
            // for even palindrome, we need to have similar logic with mid size 2
            // for that we will start right from one extra place
            left = mid;
            right = mid + 1;// for example 12333321 when we choose 33 as mid
            while (left >= 0 && right < input.length)
            {
                if (input[left] == input[right]) {
                    if (right - left > longestPalindromeEnd
                            - longestPalindromeStart) {
                        longestPalindromeStart = left;
                        longestPalindromeEnd = right;
                    }
                }
                else
                    break;
                left--;
                right++;
            }


        }
        // we have the start and end indexes for longest palindrome now
        return in.substring(longestPalindromeStart, longestPalindromeEnd + 1);
    }
public static void main(String args[]){
System.out.println(longestPalindromeString("HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE"));
}

}

cela donne tout le palindrome de la corde non seulement le plus long
Vivek Mishra

0

Cette solution est de complexité O (n ^ 2). O (1) est la complexité spatiale.

public class longestPalindromeInAString {

        public static void main(String[] args) {
            String a =  "xyMADAMpRACECARwl"; 
            String res = "";
            //String longest = a.substring(0,1);
            //System.out.println("longest => " +longest);
            for (int i = 0; i < a.length(); i++) {
                String temp = helper(a,i,i);//even palindrome
                if(temp.length() > res.length()) {res = temp ;}
                temp = helper(a,i,i+1);// odd length palindrome
                if(temp.length() > res.length()) { res = temp ;}

            }//for
            System.out.println(res);
            System.out.println("length of " + res + " is " + res.length());

        }

        private static String helper(String a, int left, int right) {
            while(left>= 0 && right <= a.length() -1  &&  a.charAt(left) == a.charAt(right)) {
                left-- ;right++ ;
            }
            String curr = a.substring(left + 1 , right);
            System.out.println("curr =>" +curr);
            return curr ;
        }

    }

0

#longest palindrome
s='HYTBCABADEFGHABCDEDCBAGHTFYW123456789987654321ZWETYGDE'
out1=[]
def substring(x):
    for i in range(len(x)):
        a=x[i:]
        b=x[:-i]
        out1.append(a)
        out1.append(b)
        
    return out1

for i in range(len(s)):
    substring(s[i:])    
final=set([item for item in out1 if len(item)>2])
final
palind={item:len(item) for item in final if item==item[::-1]}
print(palind)
sorted(palind.items(),reverse=True, key=lambda x: x[1])[0]

{'DED': 3, '123456789987654321': 18, '67899876': 8, 'ABCDEDCBA': 9, '456789987654': 12, '34567899876543': 14, 'BCDEDCB': 7, 'ABA': 3, ' 5678998765 ': 10,' 2345678998765432 ': 16,' CDEDC ': 5,' 789987 ': 6,' 8998 ': 4} (' 123456789987654321 ', 18)


-1

Voici mon algorithme:

1) définir le centre actuel comme première lettre

2) développez simultanément vers la gauche et la droite jusqu'à ce que vous trouviez le palindrome maximum autour du centre actuel

3) Si le palindrome que vous trouvez est plus grand que le palindrome précédent, mettez-le à jour

4) définir le centre actuel comme lettre suivante

5) répétez les étapes 2) à 4) pour toutes les lettres de la chaîne

Cela fonctionne en O (n).

J'espère que ça aide.


5
Considérez la chaîne "aaaaaa". Cela s'exécute en O (n ^ 2) en utilisant votre algorithme.
paislee

1
À l'origine, je pensais que l'algo n ° 1 de l'OP était le temps O (n ^ 2), mais il s'agit en fait d'un O (n ^ 3), donc même si votre algorithme ne parvient pas à atteindre la limite réalisable O (n), c'est toujours une amélioration.
j_random_hacker

C'est la solution d'extension N2 classique. MAIS, en fait, c'est proche de la solution de Manacher comme expliqué dans cette vidéo: youtube.com/watch?v=V-sEwsca1ak la différence est le point 4. Manacher réutilise les informations pour éviter de rescanner les lettres déjà scannées.
v.oddou le

-2

Référence: Wikipedia.com

Le meilleur algorithme que j'ai jamais trouvé, avec une complexité O (N)

 import java.util.Arrays;

 public class ManachersAlgorithm {

  public static String findLongestPalindrome(String s) {
    if (s==null || s.length()==0)
      return "";

    char[] s2 = addBoundaries(s.toCharArray());
    int[] p = new int[s2.length]; 
    int c = 0, r = 0; // Here the first element in s2 has been processed.
    int m = 0, n = 0; // The walking indices to compare if two elements are the same
    for (int i = 1; i<s2.length; i++) {
      if (i>r) {
        p[i] = 0; m = i-1; n = i+1;
      } else {
        int i2 = c*2-i;
        if (p[i2]<(r-i)) {
          p[i] = p[i2];
          m = -1; // This signals bypassing the while loop below. 
        } else {
          p[i] = r-i;
          n = r+1; m = i*2-n;
        }
      }
      while (m>=0 && n<s2.length && s2[m]==s2[n]) {
        p[i]++; m--; n++;
      }
      if ((i+p[i])>r) {
        c = i; r = i+p[i];
      }
    }
    int len = 0; c = 0;
    for (int i = 1; i<s2.length; i++) {
      if (len<p[i]) {
        len = p[i]; c = i;
      }
    }
    char[] ss = Arrays.copyOfRange(s2, c-len, c+len+1);
    return String.valueOf(removeBoundaries(ss));
  }

  private static char[] addBoundaries(char[] cs) {
    if (cs==null || cs.length==0)
      return "||".toCharArray();

    char[] cs2 = new char[cs.length*2+1];
    for (int i = 0; i<(cs2.length-1); i = i+2) {
      cs2[i] = '|';
      cs2[i+1] = cs[i/2];
    }
    cs2[cs2.length-1] = '|';
    return cs2;
  }

  private static char[] removeBoundaries(char[] cs) {
    if (cs==null || cs.length<3)
      return "".toCharArray();

    char[] cs2 = new char[(cs.length-1)/2];
    for (int i = 0; i<cs2.length; i++) {
      cs2[i] = cs[i*2+1];
    }
    return cs2;
  }    
}

-5

ma solution est:

static string GetPolyndrom(string str)
{
    string Longest = "";

    for (int i = 0; i < str.Length; i++)
    {
        if ((str.Length - 1 - i) < Longest.Length)
        {
            break;
        }
        for (int j = str.Length - 1; j > i; j--)
        {
            string str2 = str.Substring(i, j - i + 1);
            if (str2.Length > Longest.Length)
            {
                if (str2 == str2.Reverse())
                {
                    Longest = str2;
                }
            }
            else
            {
                break;
            }
        }

    }
    return Longest;
}

1
Cela prend un temps cubique dans la longueur de la chaîne, en raison des opérations Substring()et string-equal ( ==). C'est fondamentalement identique l'algo n ° 1 du PO.
j_random_hacker
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.