classSolution { public: stringlongestPalindrome(string s){ int n = s.size(); if (n < 2) { return s; }
int maxLen = 1; int begin = 0; // dp[i][j] 表示 s[i..j] 是否是回文串 vector<vector<int>> dp(n, vector<int>(n)); // 初始化:所有长度为 1 的子串都是回文串 for (int i = 0; i < n; i++) { dp[i][i] = true; } // 递推开始 // 先枚举子串长度 for (int L = 2; L <= n; L++) { // 枚举左边界,左边界的上限设置可以宽松一些 for (int i = 0; i < n; i++) { // 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得 int j = L + i - 1; // 如果右边界越界,就可以退出当前循环 if (j >= n) { break; }
classSolution { public: pair<int, int> expandAroundCenter(conststring& s, int left, int right) { while (left >= 0 && right < s.size() && s[left] == s[right]) { --left; ++right; } return {left + 1, right - 1}; }
stringlongestPalindrome(string s){ int start = 0, end = 0; for (int i = 0; i < s.size(); ++i) { auto [left1, right1] = expandAroundCenter(s, i, i); auto [left2, right2] = expandAroundCenter(s, i, i + 1); if (right1 - left1 > end - start) { start = left1; end = right1; } if (right2 - left2 > end - start) { start = left2; end = right2; } } return s.substr(start, end - start + 1); } };
复杂度分析:
时间复杂度:O(n^2),其中 n 是字符串的长度。长度为 1 和 2 的回文中心分别有 n 和 n−1 个,每个回文中心最多会向外扩展 O(n) 次。
classSolution { public: intexpand(conststring& s, int left, int right){ while (left >= 0 && right < s.size() && s[left] == s[right]) { --left; ++right; } return (right - left - 2) / 2; }
stringlongestPalindrome(string s){ int start = 0, end = -1; string t = "#"; for (char c: s) { t += c; t += '#'; } t += '#'; s = t;
vector<int> arm_len; int right = -1, j = -1; for (int i = 0; i < s.size(); ++i) { int cur_arm_len; if (right >= i) { int i_sym = j * 2 - i; int min_arm_len = min(arm_len[i_sym], right - i); cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len); } else { cur_arm_len = expand(s, i, i); } arm_len.push_back(cur_arm_len); if (i + cur_arm_len > right) { j = i; right = i + cur_arm_len; } if (cur_arm_len * 2 + 1 > end - start) { start = i - cur_arm_len; end = i + cur_arm_len; } }
string ans; for (int i = start; i <= end; ++i) { if (s[i] != '#') { ans += s[i]; } } return ans; } };
复杂度分析:
时间复杂度:O(n),其中 n 是字符串的长度。由于对于每个位置,扩展要么从当前的最右侧臂长 right 开始,要么只会进行一步,而 right 最多向前走 O(n) 步,因此算法的复杂度为 O(n)。