Напишите функцию, которая возвращает самый длинный палиндром в заданной строке


102

например, "ccddcc" в строке "abaccddccefe"

Я подумал о решении, но оно работает за время O (n ^ 2)

Алго 1:

Шаги: это метод грубой силы

  1. Имейте 2
    цикла for для i = от 1 до i меньше array.length -1
    для j = i + 1 to j меньше, чем array.length
  2. Таким образом можно получить подстроку всех возможных комбинаций из массива
  3. Имейте функцию палиндрома, которая проверяет, является ли строка палиндромом
  4. поэтому для каждой подстроки (i, j) вызовите эту функцию, если это палиндром, сохраните ее в строковой переменной
  5. Если вы нашли следующую подстроку палиндрома и если она больше текущей, замените ее текущей.
  6. Наконец, ваша строковая переменная получит ответ

Проблемы: 1. Этот алгоритм работает за время O (n ^ 2).

Алго 2:

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

Можете ли вы, ребята, придумать алгоритм, который будет работать в лучшее время. Если возможно O (n) раз


42
Я думаю, что первый - O(n^2)получить подстроки *, O(n)чтобы проверить, являются ли они палиндромами, всего O(n^3)?
Skylar Saveland 03

Что, если бы я знал, что работаю с палиндромом, и сохранил свои строки как две половинки, а затем, если бы я использовал Java, у меня была бы проверка O (1) для функции?
viki.omega9

10
Второй алгоритм правильный? А как насчет строки: «abcdecba». Самая большая подходящая подстрока («abcdecba» vs. «abcedcba»): «abc» или «cba». Однако оба они не палиндромы.
Yarneo

@Learner, просто любопытно, в шагах выше, на какой массив вы ссылаетесь в своих циклах for? Под массивом вы имеете в виду строку? строка.длина?
Zolt

1
для тех, кто ищет ответ с O (n ^ 2) - geeksforgeeks.org/longest-palindrome-substring-set-1
Шириш Хервэйд

Ответы:


76

Вы можете найти самый дли палиндром , используя алгоритм Manacher в в то O(n)время! Его реализацию можно найти здесь и здесь .

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


3
Я не понимаю, насколько это линейно. Я вижу whileвстроенный forэлемент с ограничением, похожим на внешний цикл.
v.oddou


9

Алго 2 может работать не для всех строк. Вот пример такой строки «ABCDEFCBA».

Не то, чтобы в строке были подстроки «ABC» и «CBA». Если вы перевернете исходную строку, это будет «ABCFEDCBA». и самая длинная совпадающая подстрока - «ABC», которая не является палиндромом.

Возможно, вам потребуется дополнительно проверить, действительно ли эта самая длинная совпадающая подстрока является палиндромом, время выполнения которого равно O (n ^ 3).


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

5

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

Внешний цикл - O (n) (макс. N-2 итераций), а внутренний цикл while - O (n) (макс. Около (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
Эльбек

1
@j_random_hacker нет, это одно из квадратичных решений. Это рассматривается здесь в качестве 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
Первоначально я думал, что алгоритм OP # 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/longest-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

Это работает даже палиндромов вы можете запустить эту программу , и дайте мне знать , если не работает для you.For понимания алгоритма любезно обратитесь к следующей ссылке stevekrenzel.com/articles/longest-palnidrome
Мохит Bhandari

@ st0le: Эта логика не будет работать даже для палиндромов, но ее можно отрегулировать даже для палиндромов. Извините, пожалуйста, за предыдущие действия. Я получил логику и обновлю ее через несколько дней, когда у меня появится время.
Mohit Bhandari

никогда не читайте свой предыдущий комментарий до сегодняшнего дня ... вы не обращались ко мне в прошлый раз .... не торопитесь, это было просто наблюдение.
st0le 09

2
Первоначально я думал, что алгоритм OP # 1 был временем O (n ^ 2), но на самом деле это бесполезно O (n ^ 3), поэтому, даже если ваш алгоритм не доживает до достижимой границы O (n), это все еще улучшение.
j_random_hacker

1

См. Статью в Википедии по этой теме. Пример реализации Java- алгоритма Манакера для линейного O (n) решения из статьи ниже:

import java.util.Arrays; открытый класс ManachersAlgorithm {общедоступный статический 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

ModifiedString = a # b # c # d # c # b # c

palinCount = 1010105010301

длина самого длинного палиндрома = 5;

самый длинный палиндром = 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

Это вернет самую длинную строку палиндрома из данной строки

-(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 Technologies.
Alex Bennett

0

Для линейного решения вы можете использовать алгоритм Манахера. Существует еще один алгоритм, вызывающий алгоритм Гасфилда, и ниже приведен код на 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) или алгоритм Манакера, в моем собственном блоге .


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
Рассмотрим строку «аааааа». Это выполняется за O (n ^ 2) с использованием вашего алгоритма.
Paislee

1
Первоначально я думал, что алгоритм OP # 1 был временем O (n ^ 2), но на самом деле это бесполезно O (n ^ 3), поэтому, даже если ваш алгоритм не доживает до достижимой границы O (n), это все еще улучшение.
j_random_hacker

Это классическое решение расширения N2. НО, на самом деле это близко к решению Manacher, как объясняется в этом видео: 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()и строкового равенства ( ==). Он в основном идентичен алгоритму OP №1.
j_random_hacker
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.