5. 最长回文子串 - 力扣(LeetCode)
给你一个字符串 s,找到 s 中最长的回文子串。
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
输入:s = "cbbd"
输出:"bb"
本题数量级不大,可以考虑暴力破解。
最简回文串有两种:
基于最简回文子串,我们向其两端扩展,比如最简回文子串的范围是 s[i],那么可以定义 L = i , R = i,只要 s[L] == s[R],则回文子串扩展成功,新的回文子串范围是 s[L, R],然后按此逻辑继续扩展 L--,R++,直到发现 s[L] != s[R] 时,停止扩展,最后 s[L+1, R - 1] 就是一个拓展处理的回文子串。
同理,比如最简回文子串时 s[i, i+1],那么可以定义 L = i ,R = i + 1,只要 s[L] == s[R],则回文子串扩展成功,新的回文子串范围是 s[L, R],然后按此逻辑继续扩展 L--,R++,直到发现 s[L] != s[R] 时,停止扩展,最后 s[L+1, R - 1] 就是一个拓展处理的回文子串。
我们可以发现,最简回文子串 s[i] 和 s[i, i+1] 的拓展逻辑是相同的,区别仅在于初始状态不同,即
因此,提取增量部分,记录到 offsets 中,即 offsets = [[0, 0], [0, 1]]
char* longestPalindrome(char* s) {
int maxLen = 0; // 记录最长回文子串的长度
int resL = 0; // 记录最长回文子串的起始位置
int offsets[2][2] = {{0, 0}, {0, 1}}; // 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]
for (int i = 0; i < strlen(s); i++) {
for (int k = 0; k < 2; k++) {
int l = i + offsets[k][0];
int r = i + offsets[k][1];
while (l >= 0 && r < strlen(s) && s[l] == s[r]) { // 扩展逻辑
l--;
r++;
}
int len = r - l - 1; // [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1
if (len > maxLen) { // 更新最长回文子串
maxLen = len;
resL = l + 1;
}
}
}
s[resL + maxLen] = '\0'; // 原地修改
return s + resL;
}
class Solution {
public:
string longestPalindrome(string s) {
int maxLen = 0; // 记录最长回文子串的长度
int resL = 0; // 记录最长回文子串的起始位置
int offsets[2][2] = {{0, 0}, {0, 1}}; // 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]
for (int i = 0; i < s.length(); i++) {
for (int k = 0; k < 2; k++) {
int l = i + offsets[k][0];
int r = i + offsets[k][1];
while (l >= 0 && r < s.length() && s[l] == s[r]) { // 扩展逻辑
l--;
r++;
}
int len = r - l - 1; // [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1
if (len > maxLen) { // 更新最长回文子串
maxLen = len;
resL = l + 1;
}
}
}
return s.substr(resL, maxLen);
}
};
class Solution {
public String longestPalindrome(String s) {
int maxLen = 0; // 记录最长回文子串的长度
int resL = 0; // 记录最长回文子串的起始位置
int[][] offsets = { { 0, 0 }, { 0, 1 } }; // 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]
for (int i = 0; i < s.length(); i++) {
for (int[] offset : offsets) {
int l = i + offset[0];
int r = i + offset[1];
while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) { // 扩展逻辑
l--;
r++;
}
int len = r - l - 1; // [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1
if (len > maxLen) { // 更新最长回文子串
maxLen = len;
resL = l + 1;
}
}
}
return s.substring(resL, resL + maxLen);
}
}
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
maxLen = 0 # 记录最长回文子串的长度
resL = 0 # 记录最长回文子串的起始位置
offsets = ((0, 0), (0, 1)) # 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]
for i in range(len(s)):
for offset in offsets:
l = i + offset[0]
r = i + offset[1]
while l >= 0 and r < len(s) and s[l] == s[r]: # 扩展逻辑
l -= 1
r += 1
length = r - l - 1 # [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1
if length > maxLen: # 更新最长回文子串
maxLen = length
resL = l + 1
return s[resL:resL + maxLen]
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function (s) {
let maxLen = 0; // 记录最长回文子串的长度
let resL = 0; // 记录最长回文子串的起始位置
const offsets = [[0, 0], [0, 1]]; // 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]
for (let i = 0; i < s.length; i++) {
for (let offset of offsets) {
let l = i + offset[0];
let r = i + offset[1];
while (l >= 0 && r < s.length && s[l] == s[r]) { // 扩展逻辑
l--;
r++;
}
const len = r - l - 1; // [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1
if (len > maxLen) { // 更新最长回文子串
maxLen = len;
resL = l + 1;
}
}
}
return s.slice(resL, resL + maxLen);
};