char[] charArray = s.toCharArray(); // 递推开始 // 先枚举子串长度 for (intL=2; L <= len; L++) { // 枚举左边界,左边界的上限设置可以宽松一些 for (inti=0; i < len; i++) { // 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得 intj= L + i - 1; // 如果右边界越界,就可以退出当前循环 if (j >= len) { break; }
classSolution: deflongestPalindrome(self, s: str) -> str: n = len(s) if n < 2: return s max_len = 1 begin = 0 # dp[i][j] 表示 s[i..j] 是否是回文串 dp = [[False] * n for _ inrange(n)] for i inrange(n): dp[i][i] = True # 递推开始 # 先枚举子串长度 for L inrange(2, n + 1): # 枚举左边界,左边界的上限设置可以宽松一些 for i inrange(n): # 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得 j = L + i - 1 # 如果右边界越界,就可以退出当前循环 if j >= n: break if s[i] != s[j]: dp[i][j] = False else: if j - i < 3: dp[i][j] = True else: dp[i][j] = dp[i + 1][j - 1] # 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置 if dp[i][j] and j - i + 1 > max_len: max_len = j - i + 1 begin = i return s[begin:begin + max_len]
classSolution { public: string longestPalindrome(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 String longestPalindrome(String s) { if (s == null || s.length() < 1) { return""; } intstart=0, end = 0; for (inti=0; i < s.length(); i++) { intlen1= expandAroundCenter(s, i, i); intlen2= expandAroundCenter(s, i, i + 1); intlen= Math.max(len1, len2); if (len > end - start) { start = i - (len - 1) / 2; end = i + len / 2; } } return s.substring(start, end + 1); }
publicintexpandAroundCenter(String s, int left, int right) { while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { --left; ++right; } return right - left - 1; } }
[sol2-Python3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: defexpandAroundCenter(self, s, left, right): while left >= 0and right < len(s) and s[left] == s[right]: left -= 1 right += 1 return left + 1, right - 1
deflongestPalindrome(self, s: str) -> str: start, end = 0, 0 for i inrange(len(s)): left1, right1 = self.expandAroundCenter(s, i, i) left2, right2 = self.expandAroundCenter(s, i, i + 1) if right1 - left1 > end - start: start, end = left1, right1 if right2 - left2 > end - start: start, end = left2, right2 return s[start: end + 1]
classSolution { public: pair<int, int> expandAroundCenter(const string& s, int left, int right){ while (left >= 0 && right < s.size() && s[left] == s[right]) { --left; ++right; } return {left + 1, right - 1}; }
string longestPalindrome(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); } };
funclongestPalindrome(s string)string { if s == "" { return"" } start, end := 0, 0 for i := 0; i < len(s); i++ { left1, right1 := expandAroundCenter(s, i, i) left2, right2 := expandAroundCenter(s, i, i + 1) if right1 - left1 > end - start { start, end = left1, right1 } if right2 - left2 > end - start { start, end = left2, right2 } } return s[start:end+1] }
funcexpandAroundCenter(s string, left, right int) (int, int) { for ; left >= 0 && right < len(s) && s[left] == s[right]; left, right = left-1 , right+1 { } return left + 1, right - 1 }
当在位置 i 开始进行中心拓展时,我们可以先找到 i 关于 j 的对称点 2 * j - i。那么如果点 2 * j - i 的臂长等于 n,我们就可以知道,点 i 的臂长至少为 min(j + length - i, n)。那么我们就可以直接跳过 i 到 i + min(j + length - i, n) 这部分,从 i + min(j + length - i, n) + 1 开始拓展。
classSolution: defexpand(self, s, left, right): while left >= 0and right < len(s) and s[left] == s[right]: left -= 1 right += 1 return (right - left - 2) // 2
deflongestPalindrome(self, s: str) -> str: end, start = -1, 0 s = '#' + '#'.join(list(s)) + '#' arm_len = [] right = -1 j = -1 for i inrange(len(s)): if right >= i: i_sym = 2 * j - i min_arm_len = min(arm_len[i_sym], right - i) cur_arm_len = self.expand(s, i - min_arm_len, i + min_arm_len) else: cur_arm_len = self.expand(s, i, i) arm_len.append(cur_arm_len) if i + cur_arm_len > right: j = i right = i + cur_arm_len if2 * cur_arm_len + 1 > end - start: start = i - cur_arm_len end = i + cur_arm_len return s[start+1:end+1:2]
classSolution { public: intexpand(const string& s, int left, int right){ while (left >= 0 && right < s.size() && s[left] == s[right]) { --left; ++right; } return (right - left - 2) / 2; }
string longestPalindrome(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; } };
funclongestPalindrome(s string)string { start, end := 0, -1 t := "#" for i := 0; i < len(s); i++ { t += string(s[i]) + "#" } t += "#" s = t arm_len := []int{} right, j := -1, -1 for i := 0; i < len(s); i++ { var cur_arm_len int if right >= i { i_sym := j * 2 - i 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 = append(arm_len, 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 } } ans := "" for i := start; i <= end; i++ { if s[i] != '#' { ans += string(s[i]) } } return ans }
funcexpand(s string, left, right int)int { for ; left >= 0 && right < len(s) && s[left] == s[right]; left, right = left-1, right+1 { } return (right - left - 2) / 2 }
funcmin(x, y int)int { if x < y { return x } return y }
复杂度分析
时间复杂度:$O(n)$,其中 $n$ 是字符串的长度。由于对于每个位置,扩展要么从当前的最右侧臂长 right 开始,要么只会进行一步,而 right 最多向前走 $O(n)$ 步,因此算法的复杂度为 $O(n)$。