104

e.g "ccddcc" in the string "abaccddccefe"

I thought of a solution but it runs in O(n^2) time

Algo 1:

Steps: Its a brute force method

  1. Have 2 for loops
    for i = 1 to i less than array.length -1
    for j=i+1 to j less than array.length
  2. This way you can get substring of every possible combination from the array
  3. Have a palindrome function which checks if a string is palindrome
  4. so for every substring (i,j) call this function, if it is a palindrome store it in a string variable
  5. If you find next palindrome substring and if it is greater than the current one, replace it with current one.
  6. Finally your string variable will have the answer

Issues: 1. This algo runs in O(n^2) time.

Algo 2:

  1. Reverse the string and store it in diferent array
  2. Now find the largest matching substring between both the array
  3. But this too runs in O(n^2) time

Can you guys think of an algo which runs in a better time. If possible O(n) time

casperOne
  • 73,706
  • 19
  • 184
  • 253
Learner
  • 2,556
  • 11
  • 33
  • 38
  • 44
    I think the first one is `O(n^2)` to get the substrings * `O(n)` to check if they are palindromes, for a total of `O(n^3)`? – Skylar Saveland Oct 03 '12 at 20:48
  • What if I knew I was working with palindrome and save my strings as two halves and then if I used Java I'd have O(1) check for the function? – viki.omega9 Mar 22 '13 at 17:03
  • 10
    The secong algo is correct? What about the string: "abcdecba". The largest matching substring is ("abcdecba" vs. "abcedcba"): "abc" or "cba". However, both are not palindromes. – Yarneo Jul 13 '13 at 10:16
  • @Learner, just curious, in you steps above what array are you refereeing to in your for loops? By array are you referring to the string? string.length? – Zolt Nov 15 '13 at 02:29
  • see in one of the answers below, the wiki: http://en.wikipedia.org/wiki/Longest_palindromic_substring – Orkun Apr 21 '14 at 12:33
  • @OrkunOzen it's complicated, and main thing is that too is of O(n^2)- while loop inside for loop – Shirish Herwade May 17 '18 at 08:15
  • 1
    for those searching answer with O(n^2) - https://www.geeksforgeeks.org/longest-palindrome-substring-set-1/ – Shirish Herwade May 17 '18 at 08:15
  • An easy solution https://youtu.be/Q3CdnFul4iE – Manoj Dec 16 '22 at 03:19

23 Answers23

75

You can find the the longest palindrome using Manacher's Algorithm in O(n) time! Its implementation can be found here and here.

For input String s = "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE" it finds the correct output which is 1234567887654321.

JJJ
  • 32,902
  • 20
  • 89
  • 102
Anuj Kulkarni
  • 2,261
  • 5
  • 32
  • 42
  • 3
    I don't understand how this is linear. i see a `while` embedded in the `for` with a bounding that seems similar to the outer loop. – v.oddou Jul 11 '16 at 09:52
  • 5
    [When someone goes on Stack Overflow, the question "answer" should actually contain an answer. Not just a bunch of directions towards the answer.](https://meta.stackexchange.com/a/8259/171858). – Erik Philips Oct 22 '18 at 17:16
9

The Algo 2 may not work for all string. Here is an example of such a string "ABCDEFCBA".

Not that the string has "ABC" and "CBA" as its substring. If you reverse the original string, it will be "ABCFEDCBA". and the longest matching substring is "ABC" which is not a palindrome.

You may need to additionally check if this longest matching substring is actually a palindrome which has the running time of O(n^3).

VCB
  • 99
  • 1
  • 1
  • 2
    It is important to note that Algo 2 should work for the "longest matching subsequence palindrome" which is a common algorithms problem where the subsequence characters can also be separated within the string. For instance, the longest matching subsequence (including character separations) between the two strings above is "ABCFCBA" which is also a palindrome :) Here a link describing the LCS problem: http://www.ics.uci.edu/~eppstein/161/960229.html – Jake Drew Dec 06 '13 at 07:10
5

As far as I understood the problem, we can find palindromes around a center index and span our search both ways, to the right and left of the center. Given that and knowing there's no palindrome on the corners of the input, we can set the boundaries to 1 and length-1. While paying attention to the minimum and maximum boundaries of the String, we verify if the characters at the positions of the symmetrical indexes (right and left) are the same for each central position till we reach our max upper bound center.

The outer loop is O(n) (max n-2 iterations), and the inner while loop is O(n) (max around (n / 2) - 1 iterations)

Here's my Java implementation using the example provided by other users.

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

The output of this is the following:

marcello:datastructures marcello$ javac LongestPalindrome
marcello:datastructures marcello$ java LongestPalindrome
String: HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE
Longest Palindrome: 12345678987654321
Marcello DeSales
  • 21,361
  • 14
  • 77
  • 80
  • 6
    If i give "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE" It does not work But anwer should be 1234567887654321 – Elbek Jun 04 '12 at 03:08
  • 1
    @j_random_hacker nope, that's one of the quadratic solutions. It's covered [here](http://articles.leetcode.com/longest-palindromic-substring-part-i/) as `expandAroundCenter`. – v.oddou Jul 14 '16 at 06:45
  • @v.oddou: You're absolutely right, and I don't know how I concluded O(n^3) given that there are only 2 nested loops! I'll delete that mistaken comment... But I've also noticed that this solution has a problem, which I'll put in a separate comment so that the author hopefully notices. – j_random_hacker Jul 14 '16 at 10:39
  • My earlier claim of O(n^3) time complexity was wrong (thanks @v.oddou for pointing this out!) but there is another problem: **this code doesn't consider even-length palindromes.** This could be fixed by adding a second, very similar outer loop (also O(n^2) so it doesn't affect the O(n^2) time complexity) that expands palindromes around each of the n-1 positions *between* each pair of characters. +2 if you fix :) – j_random_hacker Jul 14 '16 at 10:42
2

with regex and ruby you can scan for short palindromes like this:

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
neoneye
  • 50,398
  • 25
  • 166
  • 151
2

Hi Here is my code to find the longest palindrome in the string. Kindly refer to the following link to understand the algorithm http://stevekrenzel.com/articles/longest-palnidrome

Test data used is 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;     
  }
Nida Sahar
  • 698
  • 4
  • 13
  • 29
Mohit Bhandari
  • 283
  • 1
  • 2
  • 8
  • I'm not sure if this works with palindromes with even length...could you confirm? – st0le Feb 19 '11 at 09:11
  • This works for even palindromes you can run this program and let me know if is not working for you.For understanding of the algorithm kindly refer to the following link http://stevekrenzel.com/articles/longest-palnidrome – Mohit Bhandari Feb 26 '11 at 20:12
  • @st0le: This logic will not work for even palindromes but it could be adjusted for even palindromes.Kindly regret me for the earlier commnent.I got the logic and i will update it in a few days as and when i get a time. – Mohit Bhandari Mar 08 '11 at 12:52
  • never read your previous comment until today...you didn't address me last time....take your time, it was just an observation. – st0le Mar 09 '11 at 05:38
  • 2
    I originally thought the OP's algo #1 was O(n^2) time, but it's actually boneheadedly O(n^3), so even though your algorithm doesn't make it all the way to the achievable O(n) bound, it's still an improvement. – j_random_hacker Sep 16 '12 at 07:56
2

I have written the following Java program out of curiosity, simple and self-explanatory HTH. Thanks.

/**
 *
 * @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);
    }
}
Cleonjoys
  • 504
  • 4
  • 10
1

An efficient Regexp solution which avoids brute force

Starts with the entire string length and works downwards to 2 characters, exists as soon as a match is made

For "abaccddccefe" the regexp tests 7 matches before returning 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

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
brettdj
  • 54,857
  • 16
  • 114
  • 177
  • @DickKusleika can you pls update my comment at http://dailydoseofexcel.com/archives/2016/01/14/anagrams-and-palindromes/#comments with the revised code above. Thx – brettdj Feb 04 '16 at 08:45
1

See Wikipedia article on this topic. Sample Manacher's Algorithm Java implementation for linear O(n) solution from the article below:

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;   }     }
Datageek
  • 25,977
  • 6
  • 66
  • 70
1

I was asked this question recently. Here's the solution I [eventually] came up with. I did it in JavaScript because it's pretty straightforward in that language.

The basic concept is that you walk the string looking for the smallest multi-character palindrome possible (either a two or three character one). Once you have that, expand the borders on both sides until it stops being a palindrome. If that length is longer than current longest one, store it and move along.

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

This could definitely be cleaned up and optimized a little more, but it should have pretty good performance in all but the worst case scenario (a string of the same letter).

j_random_hacker
  • 50,331
  • 10
  • 105
  • 169
swilliams
  • 48,060
  • 27
  • 100
  • 130
  • 1
    I originally thought the OP's algo #1 was O(n^2) time, but it's actually boneheadedly O(n^3), so even though your algorithm doesn't make it all the way to the achievable O(n) bound, it's still an improvement. – j_random_hacker Sep 16 '12 at 07:53
  • 1
    you call this "straightforward" but it's full of `i` `j` `l` `s` `if` and state maintenance. multi return points, edge cases... – v.oddou Jul 14 '16 at 06:47
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;
    }
Sushil Mittal
  • 494
  • 4
  • 10
0

Following code calculates Palidrom for even length and odd length strings.

Not the best solution but works for both the cases

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;
}
Abhijit Gaikwad
  • 3,072
  • 28
  • 37
0
  1. Modify string to separate each character using a separator[this is to incorporate odd and even palindromes]
  2. Find palindromes around each character treating it as a center

We can find all palindromes of all length using this.

Sample :

word = abcdcbc

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

palinCount = 1010105010301

length of longest palindrome = 5;

longest palindrome = 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;

    }

}

}

nnc
  • 790
  • 2
  • 14
  • 31
0

Here i have written a logic try it :)

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

}
coldy
  • 2,115
  • 2
  • 17
  • 28
0

For linear solution, you can use Manacher's algorithm. There is another algorithm call Gusfield's Algorithm, and below is the code in 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();  
    }  
}  

You can find more on other solutions such as the best O(n^2) solution or Manacher's algorithm from my own blog.

Adriaan
  • 17,741
  • 7
  • 42
  • 75
traceformula
  • 383
  • 4
  • 4
0

This will return longest palindrome string from given string

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

== OUTPUT ===

Input: abcccde Output: ccc

Input: abcccbd Output: bcccb

Input: abedccde Output: edccde

Input: abcccdeed Output: deed

Input: abcccbadeed Output: abcccba

Kiran Patel
  • 944
  • 10
  • 16
0

Here's an implementation in 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');
alex bennett
  • 794
  • 1
  • 10
  • 17
  • Don't know why this was down-voted -- works like a charm. Got me through an interview with CA technologies just fine. – alex bennett Jun 16 '16 at 23:22
0

This Solution is of O(n^2) complexity. O(1) is the space complexity.

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

    }
Soudipta Dutta
  • 1,353
  • 1
  • 12
  • 7
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)

ashish bansal
  • 291
  • 4
  • 3
0

Try the string - "HYTBCABADEFGHABCDEDCBAGHTFYW123456789987654321ZWETYGDE"; It should work for even and odd pals. Much Thanks to Mohit!

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
    This *almost* does things in O(n^2) time. Why build `isPal` -- an O(n) operation -- only to measure its length!? Also it has a buggy attempt at handling even palindromes. On even-palindrome bugginess: `else if(input_str[i] == input_str[j])` can never succeed because that same test must have failed in the previous `if` statement; and it's buggy anyway because you can't tell just by looking at 2 characters spaced 2 positions apart whether you're looking at an even palindrome or an odd one (consider `AAA` and `AAAA`). – j_random_hacker Sep 16 '12 at 07:50
0

Program to find the longest substring which is palindrome from a given string.

 package source;
    
    import java.util.ArrayList;
            
    public class LongestPalindrome 
    {
        //Check the given string is palindrome by 
        public static boolean isPalindrome (String s)
        {
            StringBuffer sb = new StringBuffer(s);
            if(s.equalsIgnoreCase(sb.reverse().toString()))
                return true;
            else
                return false;
        }
    
        public static void main(String[] args) 
        {
            //String / word without space
            String str = "MOMABCMOMOM"; // "mom" //abccbabcd
            
            if(str.length() > 2 )
            {
                StringBuffer sb = new StringBuffer();
                ArrayList<String> allPalindromeList = new ArrayList<>();
                        
                for(int i=0; i<str.length(); i++)
                {
                    for(int j=i; j<str.length(); j++)
                    {
                        sb.append(str.charAt(j));
                        if( isPalindrome(sb.toString()) ) {
                            allPalindromeList.add(sb.toString());                       
                        }
                    }
                    //clear the stringBuffer
                    sb.delete(0, sb.length());
                }
                 
                int maxSubStrLength = -1;
                int indexMaxSubStr = -1;
                int index = -1;
                
                for (String subStr : allPalindromeList) {
                    ++index;
                    if(maxSubStrLength < subStr.length()) {
                        maxSubStrLength = subStr.length();
                        indexMaxSubStr = index;
                    }
                }
                if(maxSubStrLength > 2)
                    System.out.println("Maximum Length Palindrome SubString is : "+allPalindromeList.get(indexMaxSubStr));
                else
                    System.out.println("Not able to find a Palindrome who is three character in length!!");
            
            }
        }
    
    }
Avinash Pande
  • 1,510
  • 19
  • 17
-1

Here is my algorithm:

1) set the current center to be the first letter

2) simultaneously expand to the left and right until you find the maximum palindrome around the current center

3) if the palindrome you find is bigger than the previous palindrome, update it

4) set the current center to be the next letter

5) repeat step 2) to 4) for all letters in the string

This runs in O(n).

Hope it helps.

j_random_hacker
  • 50,331
  • 10
  • 105
  • 169
spider
  • 53
  • 5
  • 5
    Consider the the string "aaaaaa". This runs in O(n^2) using your algorithm. – calebds Jun 13 '12 at 19:12
  • 1
    I originally thought the OP's algo #1 was O(n^2) time, but it's actually boneheadedly O(n^3), so even though your algorithm doesn't make it all the way to the achievable O(n) bound, it's still an improvement. – j_random_hacker Sep 16 '12 at 07:54
  • That's the classic N2 expand solution. BUT, In fact that's close to the Manacher's solution as explained in this video: https://www.youtube.com/watch?v=V-sEwsca1ak the difference is point 4. Manacher reuse information to be able to avoid to rescan already scanned letters. – v.oddou Jul 14 '16 at 06:53
-2

Reference: Wikipedia.com

The best algorithm i have ever found, with complexity 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;
  }    
}
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
-5

my solution is :

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;
}
sjngm
  • 12,423
  • 14
  • 84
  • 114
  • 1
    This takes *cubic* time in the string length, because of the `Substring()` and string-equality (`==`) operations. It's basically identical the OP's algo #1. – j_random_hacker Sep 16 '12 at 07:56