LeetCode: Longest Palindromic Substring

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

O(n^2)的方法:44 milli secs

class Solution {
public:
    string longestPalindrome(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int nSize = s.size();
        if (nSize == NULL)  return "";
        
        int length = 1;
        const char* ps = s.c_str();
        const char* pstart = ps;
        const char* result = ps;
        while(*ps != '\0')
        {
            // odd
            const char *p1 = ps - 1;
            const char *p2 = ps + 1;
            while(p1 >= pstart && *p2 != '\0' && *p1 == *p2)
            {
                --p1;
                ++p2;
            }
            
            int tmp = p2 - p1 - 1;
            if (tmp > length)
            {
                length = tmp;
                result = p1 + 1;
            }
            
            // even
            p1 = ps;
            p2 = ps + 1;
            while(p1 >= pstart && *p2 != '\0' && *p1 == *p2)
            {
                --p1;
                ++p2;
            }
            
            tmp = p2 - p1 - 1;
            if (tmp > length)
            {
                length = tmp;
                result = p1 + 1;
            }
                
            ++ps;
        }
        
        return s.substr(result - pstart, length);
    }
};

O(n),但测试时间和上一种方法竟然一样,奇怪。(Manacher’s Algorithm)

class Solution {
public:
    string preProcess(string s)
    {
        int n = s.size();
        if (n == 0) return "^$";
        string ret = "^";
        for (int i = 0; i < n; i++)
            ret += "#" + s.substr(i, 1);
 
        ret += "#$";
        return ret;
    }
    
    string longestPalindrome(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        string T = preProcess(s);
        int n = T.size();
        int *P = new int[n];
        // C表示i之前子串中的最大回文子串中心的位置
        // R为C+P[C],也就是最大回文子串向右扩展的边界
        int C = 0, R = 0;
        for (int i = 1; i < n-1; i++)
        {
            int i_mirror = 2*C-i; // i_mirror是i关于C的对称点
            // P[i] = (R > i) ? min(R-i, P[i_mirror]) : 0;
            // 当前i在最大回文子串的边界内
            if (R > i)
            {
                // 两者区间取小的,i+P[i_mirror]的范围和R的方位
                if (R-i < P[i_mirror])
                    P[i] = R-i;
                else
                    P[i] = P[i_mirror];
            }
            else
                P[i] = 0;
            
            while (T[i + 1 + P[i]] == T[i - 1 - P[i]])
                P[i]++;
                
            if (i + P[i] > R)
            {
                C = i;
                R = i + P[i];
            }
        }
        
        // 找出p[i]中最大的
        int maxLen = 0;
        int centerIndex = 0;
        for (int i = 1; i < n-1; i++)
        {
            if (P[i] > maxLen)
            {
                maxLen = P[i];
                centerIndex = i;
            }
        }
        delete[] P;
        return s.substr((centerIndex - 1 - maxLen)/2, maxLen);
    }
};
点赞