8

Given a string of length N containing characters [A-Z], how do I determine the longest palindrome for an individual character?

I will illustrate this with an example:

Given string: JOHNOLSON In analyzing the string, we find that we have a palindrome with the character O such that the string looks like JOHNOLSON. The palindrome for the O's is of length 7 essentially looking like O--O--O. Also, notice that there is a palindrome with N, but it is only of length 6.

Another example, Given string: ABCJOHNOLSON gives the same result as above with a palindrome of the O's of length 7 looking like O--O--O.

However, with the given string ABCJOHNOLSONDA, the longest individual character palindrome is of length 14 with the character A looking like A------------A.

Other simple examples include:

ABA --> A-A (length 3)

ABAXYZ --> A-A (length 3)

ABAXYZA --> A---A (length 5), not length 7 because A-A---A is not a palindrome for the letter A.

Pay special attention to the last example because it illustrates one of the subtle nuances of the problem.

jbranchaud
  • 5,909
  • 9
  • 45
  • 70
  • 3
    There has to be a better term for what you're looking for than "palindrome" because most of your examples aren't palindromes. – Blastfurnace Nov 20 '11 at 19:44
  • Consider an example string `ABCDAEEALMNA` that when considering the `A`'s would look like `A---A--A---A` which is a palindrome (when you ignore the uniqueness of the rest of the characters) of size 12, but consider the string `ABCDAEEALMNOA` of which the whole string is no longer a palindrome, instead a much smaller substring becomes the longest palindrome, namely `A---A` of length 5 on the end. – jbranchaud Nov 20 '11 at 19:52
  • I understand the `pattern` you are interested in, it just doesn't fit the dictionary definition of the term palindrome. I wonder if there is a regular expression solution for what you're seeking. – Blastfurnace Nov 20 '11 at 20:30
  • @BlastFurnace I understand what you are saying. Would you suggest a different way of thinking about the problem? It presented itself to me as a palindrome, so I am not sure what else it could be described as. – jbranchaud Nov 21 '11 at 17:15

3 Answers3

5

You can do it in linear time, it's described here with a code sample.

Jordan Bentley
  • 1,309
  • 1
  • 8
  • 28
0

Here's what I came up with, I don't know how efficient it might be.

For every letter in the alphabet,
    Find the first and last occurrence of this letter.
    While the substring is not a palindrome for that letter (easy to check),
    find the next letter on both sides so that every possible combination is
    checked. Take the longest one and store it.
Take the longest one.
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • When you say find the next letter on both sides do you mean the next instance of the character you are currently searching for? That would fail for certain strings, such as "ABAAACAA" – Jordan Bentley Nov 20 '11 at 19:07
  • @JordanBentley: No, I mean (for example) try 0,7 then 0,6 then 0,4 then 0,3 then 0,2 then 0,0 then 2,7 then 2,6 then 2,4 then 2,3 then 2,2 then 3,7 then 3,6 then... you get the point :) But you can break if a palindrome is found under certain conditions, say immediately. – Ry- Nov 20 '11 at 19:09
  • Ah, that makes more sense. if I'm understanding it right, that would work but the worst case complexity would be O(n!) – Jordan Bentley Nov 20 '11 at 19:17
  • @JordanBentley: Yes, I thought it might not be that good. Oh well, it's an alternative :) – Ry- Nov 20 '11 at 19:30
0

Definitely not optimal. Assumes input string is all lowercase.

using System;
using System.Collections.Generic;

public class LongestPalindrome
{
    public int longest(string s)
    {
        Dictionary<char, List<int>> indices = 
            new Dictionary<char, List<int>>();

        // find all indices for each letter
        for (int i = 0; i < s.Length; i++)
        {
            char c = s[i];
            if (!indices.ContainsKey(c)) 
                    indices.Add(c, new List<int>());
            indices[c].Add(i);
        }

        int max = Int32.MinValue;

        for (int i = (int)'a'; i <= (int)'z'; i++)
        {
            char c = (char)i;

            // in case a letter didn't appear at all in the input string
            if (!indices.ContainsKey(c)) continue;

            List<int> indexList = indices[c];

            // in case a letter appeared only once in the input string
            if (indexList.Count == 1) max = Math.Max(max, 1);

            for (int j = 0; j < indexList.Count; j++)
            {
                for (int k = j + 1; k < indexList.Count; k++)
                {
                    int dist = indexList[k] - indexList[j] + 1;
                    string sub = s.Substring(indexList[j], dist);
                    if (isPalendrome(sub, c)) 
                                        max = Math.Max(max, dist);
                }   
            }
        }

        return max;
    }

    bool isPalendrome(string s, char c)
    {
        int i = 0;
        while(i < s.Length - 1 - i) 
        {
            if (s[i] != c && s[s.Length - 1 - i] != c) 
            {
                i++;
                continue;   
            }
            if (s[i] != s[s.Length - 1 - i]) return false;
            i++;
        }
        return true;
    }
}
SundayMonday
  • 19,147
  • 29
  • 100
  • 154