374 words
2 minutes
Find the longest palindromic contiguous substring

Introduction#

Given a string, find the longest palindromic contiguous substring.If there are more than one with the maximum length, return any one.

Example#

For example, the longest palindromic substring of aabcdcb is bcdcb.

The longest palindromic substring of bananas is anana.

Solution - by Manacher Algorithm#

class Solution {

    String longestPalindrome(String s) {
        char[] t = preprocess(s);
        int[] p = new int[t.length];
        int center = 0, right = 0;
        for (int i = 1; i < t.length - 1; i++) {
            int mirror = 2 * center - i;
            if (right > i) {
                p[i] = Math.min(right - i, p[mirror]);
            }
            // attempt to expand palindrome centered at i
            while (t[i + (1 + p[i])] == t[i - (1 + p[i])]) {
                p[i]++;
            }
            // if palindrome centered at i expands past right,
            // adjust center based on expanded palindrome.
            if (i + p[i] > right) {
                center = i;
                right = i + p[i];
            }
        }
        return longestPalindromicSubstring(p, s);
    }

    private String longestPalindromicSubstring(int[] p, String s) {
        int length = 0; // length of longest palindromic substring
        int center = 0; // center of longest palindromic substring
        for (int i = 1; i < p.length - 1; i++) {
            if (p[i] > length) {
                length = p[i];
                center = i;
            }
        }
        return s.substring((center - 1 - length) / 2, (center - 1 + length) / 2);
    }

    // Transform s into t.
    // For example, if s = "abba", then t = "$#a#b#b#a#@"
    // the # are interleaved to avoid even/odd-length palindromes uniformly
    // $ and @ are prepended and appended to each end to avoid bounds checking
    private char[] preprocess(String s) {
        char[] t = new char[s.length() * 2 + 3];
        t[0] = '$';
        t[s.length() * 2 + 2] = '@';
        for (int i = 0; i < s.length(); i++) {
            t[2 * i + 1] = '#';
            t[2 * i + 2] = s.charAt(i);
        }
        t[s.length() * 2 + 1] = '#';
        return t;
    }

}

Test Cases#

class SolutionTest {

    private Solution solution;
    static Collection<Object[]> data() {
        return Arrays.asList(
                new Object[][]{
                        {"aabcdcb", "bcdcb"},
                        {"bananas", "anana"},
                }
        );
    }
    
    @BeforeEach
    void setUp() {
        this.solution = new Solution();
    }
    
    @ParameterizedTest
    @MethodSource("data")
    void testSolution(String input, String expected) {
        String actual = this.solution.longestPalindrome(input);
        assertEquals(expected, actual);
    }
}

Analysis#

  • Time Complexity: O(n)
  • Space Complexity: O(n)
Find the longest palindromic contiguous substring
https://semusings.dev/posts/2019/2019-06-20-find-the-longest-palindromic-contiguous-substring/
Author
Bhuwan Prasad Upadhyay
Published at
2019-06-20