Напишіть функцію, яка повертає найдовший паліндром у заданому рядку


102

наприклад, "ccddcc" у рядку "abaccddccefe"

Я думав про рішення, але воно працює в O (n ^ 2) час

Algo 1:

Етапи: Це метод грубої сили

  1. Мати 2 для циклів
    для i = 1 до i менше, ніж масив. Довжина -1
    для j = i + 1 до j менше, ніж array.length
  2. Таким чином ви можете отримати підрядку будь-якої можливої ​​комбінації з масиву
  3. Майте функцію palindrome, яка перевіряє, чи є рядок паліндром
  4. тому для кожного підрядка (i, j) викликайте цю функцію, якщо це паліндром, збережіть її в рядковій змінній
  5. Якщо ви знайдете наступну підрядку паліндром і якщо вона більша за поточну, замініть її на поточну.
  6. Нарешті, ваша змінна строка матиме відповідь

Питання: 1. Цей алго працює в О (n ^ 2) час.

Algo 2:

  1. Переверніть рядок і збережіть його в різних масивах
  2. Тепер знайдіть найбільшу відповідну підрядку між обома масивами
  3. Але це теж працює в O (n ^ 2) час

Ви можете подумати про альго, яке працює в кращий час. По можливості O (n) час


42
Я думаю, що перший - O(n^2)отримати підряди *, O(n)щоб перевірити, чи є вони паліндромами, загалом O(n^3)?
Skylar Saveland

Що робити, якби я знав, що працюю з паліндром і зберігаю рядки як дві половини, а потім, якщо я використовую Java, я перевірив би функцію O (1)?
viki.omega9

10
Algo secong правильний? Що про рядок: "abcdecba". Найбільша відповідна підрядка ("abcdecba" vs. "abcedcba"): "abc" або "cba". Однак обидва не є паліндромами.
Ярнео

@Learner, просто цікаво, що ви крокуєте над тим, який масив ви судите в своїх петлях? За масивом ви посилаєтесь на рядок? string.length?
Золт

1
для тих, хто шукає відповідь з O (n ^ 2) - geeksforgeeks.org/longth-palindrome-substring-set-1
Shirish Herwade

Відповіді:


76

Ви можете знайти найдовший паліндром, використовуючи Алгоритм Манахера в O(n)часі! Її реалізацію можна знайти тут і тут .

Для введення String s = "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE"він знаходить правильний вихід, який є 1234567887654321.


3
Я не розумію, наскільки це лінійно. Я бачу whileвбудований в forз обмеженням, схожим на зовнішню петлю.
v.oddou


9

Algo 2 може не працювати для всіх рядків. Ось приклад такої строки "ABCDEFCBA".

Не те, що в рядку є "ABC" і "CBA" в якості підрядкового рядка. Якщо ви повернете початковий рядок, це буде "ABCFEDCBA". а найдовша відповідна підрядка - "ABC", яка не є паліндром.

Можливо, вам доведеться додатково перевірити, чи справді ця найдовша підрядна підрядка є паліндром, який має час роботи O (n ^ 3).


2
Важливо зауважити, що Algo 2 повинен працювати на "довгий збіг паліндром послідовності", що є загальною проблемою алгоритмів, де символи підрядності також можна розділити всередині рядка. Наприклад, найдовша відповідна послідовність (включаючи розділення символів) між двома рядками вище "ABCFCBA", що також є паліндром :) Тут посилання, що описує проблему LCS: ics.uci.edu/~eppstein/161/960229.html
Джейк Дрю

5

Наскільки я зрозумів проблему, ми можемо знайти паліндроми навколо центрального індексу і охопити наш пошук обома способами - праворуч і ліворуч від центру. З огляду на те, що і знаючи, що на кутах вводу немає паліндром, ми можемо встановити межі 1 та довжини-1. Звертаючи увагу на мінімальні та максимальні межі рядка, ми перевіряємо, чи символи в положеннях симетричних покажчиків (праворуч і ліворуч) однакові для кожного центрального положення, поки ми не досягнемо нашого максимального верхнього граничного центру.

Зовнішня петля - O (n) (max n-2 ітерацій), а внутрішня петля - O (n) (max навколо (n / 2) - 1 ітерація)

Ось моя реалізація Java на прикладі, наданому іншими користувачами.

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

Результатом цього є:

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

6
Якщо я даю "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE" Це не працює, але відповідь має бути 1234567887654321
Elbek

1
@j_random_hacker nope, це одне з квадратних рішень. Це розглядається тут в якості expandAroundCenter.
v.oddou

@ v.oddou: Ви абсолютно праві, і я не знаю, як я зробив висновок O (n ^ 3), враховуючи, що є лише 2 вкладені петлі! Я видалю цей помилковий коментар ... Але я також помітив, що в цьому рішенні є проблема, яку я викладу в окремому коментарі, щоб автор сподівався помітити.
j_random_hacker

Моя попередня заява про складність часу O (n ^ 3) була помилковою (спасибі @ v.oddou за вказівку на це!), Але є ще одна проблема: цей код не враховує паліндроми рівної довжини. Це можна виправити, додавши другу, дуже схожу зовнішню петлю (також O (n ^ 2), щоб вона не впливала на часову складність O (n ^ 2), яка розширює паліндри навколо кожного з n-1 позицій між кожним пара символів. +2 якщо ви виправите :)
j_random_hacker

2

за допомогою регулярного вираження та рубіну ви можете сканувати короткі паліндроми на зразок цього:

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

Я написав наступну програму Java з цікавості, простого і зрозумілого HTH. Дякую.

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

Нещодавно мені було задано це питання. Ось рішення, яке я [зрештою] придумав. Я зробив це в JavaScript, тому що це досить просто на цій мові.

Основна концепція полягає в тому, що ви ходите по рядку, шукаючи найменший можливий паліндром з кількома символами (або два, або три символи). Після цього розширюйте межі з обох сторін, поки він не перестане бути паліндром. Якщо ця довжина довша, ніж поточна, найдовша, збережіть її та рухайтеся далі.

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

Це, безумовно, може бути очищено та оптимізовано трохи більше, але воно повинно мати досить хороші показники у всьому, окрім найгіршого сценарію (рядок того самого листа).


1
Спочатку я вважав, що альго №1 ОП - це час O (n ^ 2), але це насправді O (n ^ 3), тому що, хоча ваш алгоритм не дозволяє досягти досягнутих O (n) меж, це все-таки поліпшення.
j_random_hacker

1
Ви називаєте це "прямим", але воно повне i j l s ifі державне обслуговування. кілька точок повернення, крайові випадки ...
v.oddou

1

Привіт Ось мій код, щоб знайти найдовший паліндром у рядку. Будь ласка, зверніться до наступного посилання, щоб зрозуміти алгоритм http://stevekrenzel.com/articles/longth-palnidrome

Дані тестування використовуються 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;     
  }

Я не впевнений, чи працює це з паліндромами з рівною довжиною ... Ви могли б підтвердити?
st0le

Це працює навіть для паліндромів, ви можете запустити цю програму і повідомити мені, якщо вона не працює для вас. Для розуміння алгоритму ласкаво зверніться за наступним посиланням stevekrenzel.com/articles/longth-palnidrome
Mohit Bhandari

@ st0le: Ця логіка не працюватиме навіть для паліндромів, але вона може бути налаштована навіть на паліндроми. Ласкаво пошкодуйте про попередній комнент. Я отримав логіку, і я оновлю її через кілька днів, як і коли я отримаю час.
Мохіт Бхандарі

ніколи не читав твій попередній коментар до сьогоднішнього дня ... ти не звертався до мене востаннє .... забирай час, це було лише спостереження.
st0le

2
Спочатку я вважав, що альго №1 ОП - це час O (n ^ 2), але це насправді O (n ^ 3), тому що, хоча ваш алгоритм не дозволяє досягти досягнутих O (n) меж, це все-таки поліпшення.
j_random_hacker

1

Дивіться статтю Вікіпедії на цю тему. Приклад Manacher в Алгоритм реалізації Java для лінійного O (N) розчину зі статті нижче:

імпорт 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

Ефективне Regexpрішення, що дозволяє уникнути грубої сили

Починається з усієї довжини рядка і працює вниз до 2 символів, існує, як тільки відбувається відповідність

Для "abaccddccefe"тестування регулярного вибору 7 матчів перед поверненням 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

функція

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 чи можете ви оновити мій коментар на dailydoseofexcel.com/archives/2016/01/14/… з переглянутим кодом вище. 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

Спробуйте рядок - "HYTBCABADEFGHABCDEDCBAGHTFYW123456789987654321ZWETYGDE"; Це повинно працювати для парних і непарних друзів. Велике спасибі Мохіту!

використання простору імен 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
Це майже робить речі в O (n ^ 2) час. Навіщо будувати isPal- операцію O (n) - лише для вимірювання її довжини !? Крім того, він має помилку намагатися обробляти навіть паліндром. Що стосується рівномірного паліндромного виснаження: else if(input_str[i] == input_str[j])ніколи не може досягти успіху, оскільки той самий тест, мабуть, не вдався до попереднього ifтвердження; і все одно це баггі, тому що ви не можете сказати, лише дивлячись на 2 символи, розташовані на 2 положення один від одного, чи дивитесь ви на рівний паліндром чи непарний (врахуйте AAAта AAAA).
j_random_hacker

0

Наступний код обчислює Palidrom для рівних довжин і непарних рядків.

Не найкраще рішення, але працює в обох випадках

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. Змініть рядок для відокремлення кожного символу за допомогою роздільника [для включення непарних і парних паліндрів]
  2. Знайдіть паліндроми навколо кожного персонажа, трактуючи його як центр

За допомогою цього ми можемо знайти всі паліндроми різної довжини.

Зразок:

слово = abcdcbc

modiString = a # b # c # d # c # b # c

palinCount = 1010105010301

довжина найдовшого паліндрому = 5;

найдовший паліндром = bcdcb

публічний клас 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

Це поверне найдовшу паліндромну рядок із заданого рядка

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

== ВИХІД ===

Вхід: abcccde Вихід: ccc

Вхід: abcccbd Вихід: bcccb

Вхід: abedccde Вихід: edccde

Вхід: abcccdeed Вихід: акт

Вхід: abcccbadeed Вихід: abcccba


0

Ось реалізація в 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');


Не знаю, чому це було знято - це як принадність. Мене чудово пройшло інтерв'ю з технологіями CA.
Алекс Беннетт

0

Для лінійного рішення можна використовувати алгоритм Manacher. Є ще один алгоритм виклику Алгоритму Гусфілда, а нижче - код у 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();  
    }  
}  

Ви можете знайти більше про інші рішення, такі як найкраще рішення O (n ^ 2) або алгоритм Manacher з мого власного блогу .


0

Ось я написав логіку спробуйте :)

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

}

це дає всім паліндром у струні не тільки найдовший
Вівек Мішра

0

Цей Розв’язок має складність O (n ^ 2). O (1) - складність простору.

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

Ось мій алгоритм:

1) встановити поточний центр першою літерою

2) одночасно розширюйтесь вліво і вправо, поки не знайдете максимальний паліндром навколо поточного центру

3) якщо паліндром, який ви знайшли, більший за попередній паліндром, оновіть його

4) встановити поточний центр наступним листом

5) повторіть крок 2) до 4) для всіх літер у рядку

Це працює в O (n).

Сподіваюся, це допомагає.


5
Розглянемо рядок "aaaaaa". Це працює в O (n ^ 2), використовуючи ваш алгоритм.
paislee

1
Спочатку я вважав, що альго №1 ОП - це час O (n ^ 2), але це насправді O (n ^ 3), тому що, хоча ваш алгоритм не дозволяє досягти досягнутих O (n) меж, це все-таки поліпшення.
j_random_hacker

Це класичне рішення розширення N2. АЛЕ, насправді це близько до рішення Манахера, як пояснено у цьому відео: youtube.com/watch?v=V-sEwsca1ak різниця полягає у точці 4. Менеджер повторно використовує інформацію, щоб уникнути повторної перевірки вже відсканованих листів.
v.oddou

-2

Довідка: Wikipedia.com

Найкращий алгоритм, який я коли-небудь знаходив, зі складністю 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

моє рішення:

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
Це займає кубічний час у довжині рядка через операції Substring()та string-рівність ( ==). Це в основному ідентичне альго №1 ОП.
j_random_hacker
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.