Thursday, March 8, 2012

Manacher's algorithm


Longest palindromic substring is the problem of finding a maximum-length substring of a given string that is also a palindrome. Usually this can be done by dynamic programming or suffix array. However, Manacher's algorithm is a more efficient algorithm that takes only O(n) time.

The main idea is to turn odd/even palindromic substring into odd palindromic string. We add special characters among original characters. For example, we convert 'abba' to '#a#b#b#a#', 'aba' to '#a#b#a#'. And add '$' at the front of the string for handling edge cases.

Let's assume S = '1221' as to illustrate our algorithm. S' = '$#1#2#2#1#'. And we let array P to store the extension to the left(or right) in S'. So here,
S  #  1  #  2  #  2  #  1  #
P  1  2  1  2  5  2  1  2  1

P.S. P[i] - 1 is the length of the original palindrome.

Next question is how to calculate array P. Let id be the max palindromic substring's center, and mx = id + P[id], i.e., the right end of the substring. Then we have the following property:

    If mx > i, the P[i] >= min(P[2 * id - i], mx - i)


int mancher(){
    int mx = 0, id, i, ans = 0;
    memset(p, 0, sizeof(p));

    for (i = 1; i < m; i++){
        if (mx > i){
            p[i] = min(p[2 * id - i], mx - i);
        } else {
            p[i] = 1;
        }
        for ( ; str2[i - p[i]] == str2[i + p[i]]; p[i]++);
        if (i + p[i] > mx){
            mx = i + p[i];
            id = i;
        }
    }
    for (i = 0; i < m; i++){
        ans = max(ans, p[i]);
    }
    ans--;
    return ans;
}

No comments:

Post a Comment