Friday, November 20, 2015

Longest palindrome starting from left side

This problem is from Li Peng's blog: http://www.allenlipeng47.com/PersonalPage/index/view/202/nkey

Given a string, find the longest length of palindrome starting from the left.
For example:
abaeab, the longest from left is aba, so return 3.
abcbaef, the longest from left is abcba, so return 5.
ababa, the longest from left is ababa, so return 5.

One solution is to start a pointer p from right,  check if substring between index 0 and p is palindrome, if found, return it substring, if not, move pointer to the left and continue search.
Time complexity is O(n^2), since p goes from n-1 to 0, each palindrome check takes about n.

A linear solution is using KMP algorithm. First of all, we generate the reverse string of the original string:

abaeab -> baeaba

Now we are going to do pattern match between these two strings, we treat original string as the pattern, the reverse string as the text to be matched, however the difference here is that when we reach the end of reverse string, we find the long palindrome!

Failure table for string abaeba
  a  b  a  e  b  a
 -1 0  0  0  0  0

First try: failed and move to next
 baeaba
 abaeab

baeaba: failed and move to next
  abaeab

......

baeaba
      abaeab

Found!

We are going to use KMP algorithm to help us to do the pattern matching so our algorithm can be run in linear time.

The first operation is to build the KMP failure function.

public static int[] buildTable(char[] digits){
        int[] table = new int[digits.length+1];
        table[0] = -1;
        int i = 1, j = -1;
        while(i<digits.length){
            while(j>=0 && digits[i]!=digits[j])
                j = table[j];
            i++;
            j++;
            table[i] = j;       
        }
        return table;
    }

Once we have the failure function, we can skip some characters in the pattern based on the failure function, and the while loop will exit when we reach the end of the text itself.

public static String longestPalindromeFromLeft(String s){
        char[] pattern = s.toCharArray();
        char[] text = new StringBuilder(s).reverse().toString().toCharArray();
       
        int[] table = buildTable(pattern);
       
        int j = 0, i = 0;
        while(i<text.length){
            while(j>=0  && text[i]!=pattern[j])
                j = table[j];
            i++;
            j++;
        }
       
        return s.substring(0, j);
    }
   


No comments:

Post a Comment