最长回文子串

Manacher’s Algorithm

具体解释可以看http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

基本思路是,预处理原字符串,在字符之间插入特殊字符“#”, 这样计算出来的回文长度总是奇数,其半径正好等于原字符串的回文长度。

记录以当前位置i为中心的回文半径长度dp[i],如果i在之前某个中心c的半径r之内,即c+r > i,则dp[i]的计算可以重用它的对称点mirror = c - (i-c)的结果。

如果dp[mirror] > r-i,即str[i - (r-i) ... r]是以i为中心的回文,还可以继续扩展

否则str[i - dp[mirror]... i+dp[mirror]]是以i为中心的回文,半径等于dp[mirror];

class Solution {
public:
    string longestPalindrome(string s) {
        string t = preprocess(s);
        int n = t.size();
        vector<int> dp(n, 0);
        int c = 0, r = 0;
        for (int i = 1; i < n-1; ++i) {
            int mirror = c * 2 - i;
            dp[i] = (r > i) ? min(r-i, mirror >= 0 ? dp[mirror] : 0) : 0;
            while (t[i+dp[i]+1] == t[i-dp[i]-1]) ++dp[i];
            if (dp[i]+i > r) {
                c = i;
                r = dp[i]+i;
            }
        }
        int ma = 0;
        c = 0;
        for (int i = 1; i < n-1; ++i) {
            if (dp[i] > ma) {
                ma = dp[i];
                c = i;
            }
        }
        int start = (c-dp[c])/2;
        return s.substr(start, dp[c]);
    }
    
    string preprocess(string &s) {
        string ret = "#";
        for (int i = 0; i < s.size(); ++i) {
            ret += s.substr(i, 1) + "#";
        }
        return ret;
    }
};

  

 

posted @ 2013-06-12 15:39  断桥残雪  阅读(218)  评论(0编辑  收藏  举报