Napisz funkcję, która zwraca najdłuższy palindrom w podanym ciągu


102

np. „ccddcc” w ciągu „abaccddccefe”

Pomyślałem o rozwiązaniu, ale działa ono w czasie O (n ^ 2)

Algo 1:

Kroki: To metoda brutalnej siły

  1. Miej 2 pętle
    for dla i = 1 do i mniej niż array.length -1
    dla j = i + 1 do j mniej niż array.length
  2. W ten sposób możesz uzyskać podciąg każdej możliwej kombinacji z tablicy
  3. Miej funkcję palindromową, która sprawdza, czy łańcuch jest palindromem
  4. więc dla każdego podciągu (i, j) wywołaj tę funkcję, jeśli jest to palindrom, zapisz ją w zmiennej łańcuchowej
  5. Jeśli znajdziesz następny podciąg palindromu i jeśli jest większy niż bieżący, zastąp go bieżącym.
  6. Wreszcie twoja zmienna łańcuchowa będzie miała odpowiedź

Problemy: 1. Ten algorytm działa w czasie O (n ^ 2).

Algo 2:

  1. Odwróć ciąg i zapisz go w innej tablicy
  2. Teraz znajdź największy pasujący podciąg między obiema tablicami
  3. Ale to też przebiega w czasie O (n ^ 2)

Czy możecie pomyśleć o algo, które działa w lepszym czasie. Jeśli to możliwe, czas O (n)


42
Myślę, że pierwszym z nich jest O(n^2)pobranie podciągów *, O(n)aby sprawdzić, czy są to palindromy, w sumie O(n^3)?
Skylar Saveland

A co, gdybym wiedział, że pracuję z palindromem i zapisuję ciągi jako dwie połówki, a gdybym użył Javy, miałbym O (1) sprawdzenie funkcji?
viki.omega9

10
Drugie algo jest poprawne? A co z napisem: „abcdecba”. Największy pasujący podciąg to („abcdecba” kontra „abcedcba”): „abc” lub „cba”. Jednak oba nie są palindromami.
Yarneo

@Learner, po prostu zaciekawiony, czy kroczysz wyżej, do jakiej tablicy kierujesz się w swoich pętlach for? Czy przez tablicę odnosisz się do ciągu? Długość łańcucha?
Zolt

1
dla tych, którzy szukają odpowiedzi z O (n ^ 2) - geeksforgeeks.org/longest-palindrome-substring-set-1
Shirish Herwade

Odpowiedzi:


76

Możesz znaleźć najdłuższy palindrom za pomocą algorytmu Manachera w O(n)czasie! Jego implementację można znaleźć tutaj i tutaj .

Dla danych wejściowych String s = "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE"znajduje prawidłowe wyjście, którym jest 1234567887654321.


3
Nie rozumiem, jak to jest liniowe. widzę whileosadzony w forz ograniczeniem, które wydaje się podobne do zewnętrznej pętli.
v.oddou,


9

Algo 2 może nie działać dla wszystkich ciągów. Oto przykład takiego ciągu „ABCDEFCBA”.

Nie chodzi o to, że łańcuch ma „ABC” i „CBA” jako podciąg. Jeśli odwrócisz oryginalny ciąg, będzie to „ABCFEDCBA”. a najdłuższym pasującym podciągiem jest „ABC”, który nie jest palindromem.

Może być konieczne dodatkowe sprawdzenie, czy ten najdłuższy pasujący podciąg jest w rzeczywistości palindromem, którego czas działania wynosi O (n ^ 3).


2
Należy zauważyć, że algorytm Algo 2 powinien działać dla „najdłuższego pasującego palindromu podciągów”, co jest częstym problemem algorytmów, w którym znaki podciągów mogą być również rozdzielane w ciągu. Na przykład, najdłuższym pasującym podciągiem (w tym separacją znaków) między dwoma powyższymi ciągami jest „ABCFCBA”, który jest również palindromem :) Tutaj link opisujący problem LCS: ics.uci.edu/~eppstein/161/960229.html
Jake Drew

5

O ile zrozumiałem problem, możemy znaleźć palindromy wokół środkowego indeksu i rozciągnąć nasze poszukiwania w obie strony, na prawo i lewo od środka. Biorąc to pod uwagę i wiedząc, że w rogach wejścia nie ma palindromu, możemy ustawić granice na 1 i długość-1. Zwracając uwagę na minimalne i maksymalne granice łańcucha, sprawdzamy, czy znaki na pozycjach indeksów symetrycznych (prawy i lewy) są takie same dla każdej pozycji centralnej, aż osiągniemy maksymalny górny środek ograniczający.

Pętla zewnętrzna to O (n) (max n-2 iteracji), a wewnętrzna pętla while to O (n) (max około (n / 2) - 1 iteracja)

Oto moja implementacja Java na przykładzie dostarczonym przez innych użytkowników.

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);
    }
}

Wynik tego jest następujący:

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

6
Jeśli podam „HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE” To nie działa Ale odpowiedź powinna być 1234567887654321
Elbek

1
@j_random_hacker nope, to jedno z rozwiązań kwadratowych. Jest tutaj objęty jako expandAroundCenter.
v.oddou,

@ v.oddou: Masz całkowitą rację i nie wiem, jak doszedłem do wniosku O (n ^ 3), biorąc pod uwagę, że są tylko 2 zagnieżdżone pętle! Usuwam ten błędny komentarz ... Ale zauważyłem też, że to rozwiązanie ma problem, który umieszczę w osobnym komentarzu, aby autor miał nadzieję, że to zauważył.
j_random_hacker,

Moje wcześniejsze twierdzenie o złożoności czasowej O (n ^ 3) było błędne (dzięki @ v.oddou za wskazanie tego!), Ale jest inny problem: ten kod nie uwzględnia palindromów o parzystej długości. To może być ustalone przez dodanie drugiej, bardzo podobny pętli zewnętrznej (także O (N ^ 2) tak, że nie wpływa on O (N ^ 2) Złożoność), który rozszerza się Palindromes wokół każdego z n-1 pozycji między sobą para znaków. +2 jeśli naprawisz :)
j_random_hacker

2

za pomocą wyrażeń regularnych i ruby ​​możesz szukać krótkich palindromów, takich jak ten:

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

Poniższy program w Javie napisałem z ciekawości, prosty i nie wymagający wyjaśnień HTH. Dzięki.

/**
 *
 * @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

Ostatnio zadano mi to pytanie. Oto rozwiązanie, które [ostatecznie] wymyśliłem. Zrobiłem to w JavaScript, ponieważ jest to dość proste w tym języku.

Podstawową koncepcją jest to, że idziesz po łańcuchu w poszukiwaniu najmniejszego możliwego palindromu wieloznakowego (dwu- lub trzyznakowego). Gdy już to zrobisz, rozszerz granice po obu stronach, aż przestanie być palindromem. Jeśli ta długość jest dłuższa niż obecnie najdłuższa, zapisz ją i przejdź dalej.

// 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;
}

Zdecydowanie można to nieco bardziej oczyścić i zoptymalizować, ale powinno mieć całkiem dobrą wydajność we wszystkich scenariuszach oprócz najgorszego przypadku (ciąg tej samej litery).


1
Początkowo myślałem, że algorytm nr 1 OP to czas O (n ^ 2), ale w rzeczywistości jest to bezczelny O (n ^ 3), więc nawet jeśli twój algorytm nie pokonuje całej drogi do osiągalnego O (n) związanego, to wciąż poprawa.
j_random_hacker

1
nazywasz to „prostym”, ale jest pełne i j l s ifi utrzymywane w stanie. wiele punktów zwrotnych,
skrajne

1

Cześć Oto mój kod, aby znaleźć najdłuższy palindrom w ciągu. Prosimy zapoznać się z poniższym linkiem, aby zrozumieć algorytm http://stevekrenzel.com/articles/longest-palnidrome

Użyte dane testowe to 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;     
  }

Nie jestem pewien, czy to działa z palindromami o równej długości ... czy mógłbyś potwierdzić?
st0le

Działa to nawet dla palindromów, możesz uruchomić ten program i daj mi znać, jeśli nie działa dla Ciebie.Aby zrozumieć algorytm, prosimy o zapoznanie się z następującym linkiem stevekrenzel.com/articles/longest-palnidrome
Mohit Bhandari

@ st0le: Ta logika nie będzie działać nawet dla palindromów, ale można ją dostosować nawet dla palindromów. Proszę mi żałować za wcześniejsze commnent. Mam logikę i zaktualizuję ją za kilka dni, kiedy będę miał czas.
Mohit Bhandari

nigdy nie czytaj swojego poprzedniego komentarza aż do dzisiaj… nie zwracałeś się do mnie ostatnim razem… nie spiesz się, to była tylko obserwacja.
st0le

2
Początkowo myślałem, że algorytm nr 1 OP to czas O (n ^ 2), ale w rzeczywistości jest to bezczelny O (n ^ 3), więc nawet jeśli twój algorytm nie pokonuje całej drogi do osiągalnego O (n) związanego, to wciąż poprawa.
j_random_hacker,

1

Zobacz artykuł w Wikipedii na ten temat. Przykładowa implementacja algorytmu Java firmy Manacher dla liniowego rozwiązania O (n) z artykułu poniżej:

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;   }     }

1

Skuteczne Regexprozwiązanie, które pozwala uniknąć brutalnej siły

Rozpoczyna się od całej długości łańcucha i działa w dół do 2 znaków, istnieje zaraz po dopasowaniu

Dla "abaccddccefe"testów regexp 7 dopasowań przed powrotem 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

funkcjonować

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, czy możesz zaktualizować mój komentarz na dailydoseofexcel.com/archives/2016/01/14/ ... z poprawionym kodem powyżej. Dzięki
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

Wypróbuj ciąg - "HYTBCABADEFGHABCDEDCBAGHTFYW123456789987654321ZWETYGDE"; Powinien działać dla parzystych i nieparzystych kumpli. Wielkie dzięki dla Mohita!

using namespace 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
To prawie robi rzeczy w czasie O (n ^ 2). Po co budować isPal- operację O (n) - tylko po to, by zmierzyć jej długość !? Ma również wadliwą próbę radzenia sobie nawet z palindromami. W przypadku błędu z parzystym palindromem: else if(input_str[i] == input_str[j])nigdy nie może się powieść, ponieważ ten sam test musiał zakończyć się niepowodzeniem w poprzedniej ifinstrukcji; i tak jest wadliwy, ponieważ po prostu patrząc na 2 znaki oddalone od siebie o 2 pozycje nie można stwierdzić, czy patrzysz na parzysty czy nieparzysty palindrom (rozważ AAAi AAAA).
j_random_hacker,

0

Poniższy kod oblicza Palidrom dla ciągów o parzystej i nieparzystej długości.

Nie jest to najlepsze rozwiązanie, ale działa w obu przypadkach

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. Zmodyfikuj ciąg, aby oddzielić każdy znak za pomocą separatora [ma to na celu włączenie nieparzystych i parzystych palindromów]
  2. Znajdź palindromy wokół każdej postaci, traktując ją jako centrum

Za pomocą tego możemy znaleźć wszystkie palindromy dowolnej długości.

Próbka:

słowo = abcdcbc

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

palinCount = 1010105010301

długość najdłuższego palindromu = 5;

najdłuższy palindrom = bcdcb

public class 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

To zwróci najdłuższy łańcuch palindromowy z podanego ciągu

-(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"];
}

== WYJŚCIE ===

Wejście: abcccde Wyjście: ccc

Dane wejściowe: abcccbd Dane wyjściowe: bcccb

Wejście: abedccde Wyjście: edccde

Dane wejściowe: abcccdeed Dane wyjściowe: akt

Dane wejściowe: abcccbadeed Dane wyjściowe: abcccba


0

Oto implementacja w 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');


Nie wiem, dlaczego głosowano w dół - działa jak urok. Przeprowadził mnie wywiad z technologiami CA.
alex bennett

0

W przypadku rozwiązania liniowego można użyć algorytmu Manachera. Istnieje inny algorytm nazywający algorytm Gusfielda, a poniżej jest kod w 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();  
    }  
}  

Więcej o innych rozwiązaniach, takich jak najlepsze rozwiązanie O (n ^ 2) czy algorytm Manachera, można znaleźć na moim blogu .


0

Tutaj napisałem logikę, spróbuj :)

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"));
}

}

to daje cały palindrom w strunie nie tylko najdłuższy
Vivek Mishra

0

To rozwiązanie ma złożoność O (n ^ 2). O (1) to złożoność przestrzeni.

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

Oto mój algorytm:

1) ustaw bieżące centrum na pierwszą literę

2) jednocześnie rozszerzaj się w lewo iw prawo, aż znajdziesz maksymalny palindrom wokół aktualnego środka

3) jeśli znaleziony palindrom jest większy niż poprzedni, zaktualizuj go

4) ustaw bieżące centrum na następną literę

5) powtórz kroki od 2) do 4) dla wszystkich liter w ciągu

To działa w O (n).

Mam nadzieję, że to pomoże.


5
Rozważmy ciąg „aaaaaa”. Działa to w O (n ^ 2) przy użyciu twojego algorytmu.
paislee

1
Początkowo myślałem, że algorytm nr 1 OP to czas O (n ^ 2), ale w rzeczywistości jest to bezczelny O (n ^ 3), więc nawet jeśli twój algorytm nie pokonuje całej drogi do osiągalnego O (n) związanego, to wciąż poprawa.
j_random_hacker,

To klasyczne rozwiązanie N2 expand. ALE, w rzeczywistości jest to bliskie rozwiązaniu Manachera, jak wyjaśniono w tym filmie: youtube.com/watch?v=V-sEwsca1ak różnica polega na punkcie 4. Manacher ponownie wykorzystuje informacje, aby móc uniknąć ponownego skanowania już zeskanowanych listów.
v.oddou

-2

Źródła: Wikipedia.com

Najlepszy algorytm, jaki kiedykolwiek znalazłem, ze złożonością 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

moje rozwiązanie to:

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
Zajmuje to sześcienny czas na długość łańcucha z powodu operacji Substring()i string-equality ( ==). Jest to w zasadzie identyczny algorytm OP nr 1.
j_random_hacker,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.