DP专题
5. Longest Palindromic Substring 最长回文子串
题意:找到字符串的最长回文子串(子串是连续的,子序列是可以间断的)
我的解法:将每两个字符中间插入一个‘#’,这个就可以一起判断奇数回文串和偶数回文串,分别将每个字符作为中心往两侧最长回文,更新结果。时间复杂度O(n^2)
我的代码:
class Solution { public: string longestPalindrome(string s) { string ss, ret; for (int i = 0; i < s.size(); i++) { ss += '#'; ss += s[i]; } ss += '#'; int ans = 0, n = ss.size(); for (int i = 0; i < n; i++) { int j = 1; while (i+j < n && i-j >= 0 && ss[i+j] == ss[i-j]) j++; if (ss[i] == '#') { if (j > ans) { ans = j; ret = ss.substr(i-j+1, 2*j-1); } } else { if (j-1 >= ans) { ans = j-1; ret = ss.substr(i-j+1, 2*j-1); } } } string gg; for (int i = 0; i < ret.size(); i++) if (ret[i] != '#') gg += ret[i]; return gg; } };
最优解:Manacher算法,时间、空间复杂度O(n)
Manacher算法:https://segmentfault.com/a/1190000003914228
代码:
class Solution { public: string longestPalindrome(string s) { string ss = "#", tmp, ret; for (int i = 0; i < s.size(); i++) ss = ss+s[i]+'#'; int n = ss.size(), MaxRight = 0, pos = 0; vector<int> RL(n, 0); for (int i = 0; i < n; i++) { if (i < MaxRight) RL[i] = min(RL[2*pos-i], MaxRight-i); else RL[i] = 1; while (i-RL[i] >= 0 && i+RL[i] < n && ss[i-RL[i]] == ss[i+RL[i]]) RL[i]++; if (i+RL[i]-1 > MaxRight) { MaxRight = i+RL[i]-1; pos = i; } if (2*RL[i]-1 > tmp.size()) tmp = ss.substr(i-RL[i]+1, 2*RL[i]-1); } for (int i = 0; i < tmp.size(); i++) if (tmp[i] != '#') ret += tmp[i]; return ret; } };