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.

class Solution {
private:
    const char sep_char     = '\1';
public:
    string longestPalindrome(string s) {
        int max_len = 0;
        int len = s.length();
        if (len <= 1) return s;
        
        string str;
        str.push_back(sep_char);
        for (int i=0; i<len; i++) {
            str.push_back(s[i]);
            str.push_back(sep_char);
        }
        int nlen = 2 * len + 1;
        vector<int> P(nlen, 0);
        
        int last_i = 0;
        int last_r = 0;
        
        int maxv = -1;
        int maxi = -1;

        for (int i=0; i<nlen; i++) {
            int p = i, q = i;
            if (i < last_r) {
                int j = 2 * last_i - i;     // (i + j) / 2 = last_i
                int slen = min(P[j], last_r - i);
                p-= slen;
                q+= slen;
            }
            
            while(p >= 0 && q < nlen && str[p] == str[q]) p--, q++;
            if (q > last_r) {
                last_r = q;
                last_i = i;
            }

            P[i] = q - i;
            
            if (P[i] > maxv) {
                maxv = P[i];
                maxi = i;
            }
        }
        return s.substr((maxi + 1 - P[maxi]) / 2, P[maxi] - 1);
    }
};

Manacher算法实现,不能懈怠

第二轮:

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.

以前做得真是没什么印象了,因为题目中规定了不超过1000数量不大,先写个简单的:

// 13:37
class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        if (n <= 1) {
            return s;
        }
        const char* str = s.c_str();
        
        int maxlen = 1;
        int ts = 0, te = 0;
        int ms = 0, me = 0;
        for (int i=0; i<n; i++) {
            int tlen = countPal(str, i, n, ts, te);
            if (tlen > maxlen) {
                maxlen = tlen;
                ms = ts;
                me = te;
            }
        }
        return s.substr(ms, me-ms+1);
    }
    
    int countPal(const char* str, int mid, int n, int& s, int& e) {
        if (mid < 0 || mid >= n) return 0;
        int maxlen = 1;
        int l = mid - 1;
        int r = mid + 1;
        s = l;
        e = r;
        while (l >= 0 && r < n && str[l] == str[r]) {
            if (r - l + 1 > maxlen) {
                maxlen = r-l+1;
                s = l;
                e = r;
            }
            l--, r++;
        }
        l = mid;
        r = mid + 1;
        while (l >= 0 && r < n && str[l] == str[r]) {
            if (r - l + 1 > maxlen) {
                maxlen = r - l + 1;
                s = l;
                e = r;
            }
            l--, r++;
        }
        return maxlen;
    }
};

 

i为当前遍历到的字符,如果它在一个已知的回文串内(即last_r>i,last_r为已知的回文串中右端最靠右的索引+1),那么在这个回文串内存在一个和i关于该回文串中心last_i的一个对称位置j(设已经由先前步骤记录为last_i,它和last_r是同一个已知回文串的参数)。如果在j位置上存在一定长度的回文串,那么在i上也回同样的存在。但它们的长度很可能是不一样的,有下面几种情况

1. 如图中的情况A段回文串已经超出了以last_i为中心的回文范围,所以我们可以直接判断是回文的部分只有B段,剩下的部分还是需要一一比较。

2. 如果图中的A段完全在已知回文串内,则以i为中心的回文串至少和以j为中心的回文长度一致,外延部分需要逐一比较

int slen = min(P[j], last_r - i);
P为存储回文中心到回文外延的长度数组


改写一下代码:
class Solution {
public:
    string longestPalindrome(string s) {
        int len = s.size();
        
        string ms = "$";
        for (int i=0; i<len; i++) {
            ms.push_back(s[i]);
            ms.push_back('$');
        }
        
        int mlen = ms.size();
        vector<int> dp(mlen, 1);
        
        int far = 0;
        int lcenter = 0;
        int maxlen = 0;
        int center = 0;
        
        for (int i=0; i<mlen; i++) {
            int p = i, q = i;
            if (i < far) {
                int mirror = 2 * lcenter - i;
                int step = min(far - i, dp[mirror]);
                p-=step;
                q+=step;
            }
            while (p >= 0 && q < mlen && ms[p] == ms[q]) {
                p--, q++;
            }
            if (q > far) {
                far = q;
                lcenter = i;
            }
            dp[i] = q - i;
            if (dp[i] > maxlen) {
                maxlen = dp[i];
                center = i;
            }
        }
        
        int slen = (maxlen * 2 - 1) / 2;
        int start = (center - maxlen + 1) / 2;
        return s.substr(start, slen);
    }
};

 

posted @ 2014-09-11 00:31  卖程序的小歪  阅读(253)  评论(0编辑  收藏  举报