最长回文子串
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; } };