题目描述
找出字符串里最长的回文子串(连续)。
s = "babad"
输出 = "bab"(或 "aba",都对)
思路解析
所有子串有 n² 个,每个判回文还要 O(n),总共 O(n³)。换个思路:回文一定有个中心,从中心往两边扩,能省一个量级。
对每个中心,左右指针一起向外走,只要 s[l]==s[r] 就继续扩;一旦不等或越界就停,记录这段长度。中心有两种:单字符(奇回文)和两字符之间(偶回文),都试一遍取最长。
以下标 1 的 a 为中心:从中心 a(下标 1)开始,l=r=1。单字符本身就是长度 1 的回文,向两边扩。
向外扩 · b == b ✓:l 退到 0(b)、r 进到 2(b),s[0]==s[2],是回文!当前回文 "bab",长度 3。继续往外扩。
再扩 · 越界,停:l 再退就到 −1 越界,停止。以 a 为中心扩出的最长回文是 "bab"(长度 3)。
其它中心 · 都不更长:再试其它中心,比如以下标 2 为中心能扩出 "aba"(也是 3),但没有更长的。最终答案长度 3。
抓住"回文关于中心对称"这一点,就能把"判断 + 枚举"合二为一:从中心往外扩,扩到哪算到哪。回文子串计数、最长回文子序列都和它相关。
参考代码(Python)
Python
1def expand(l, r): # 从中心向两边扩
2 while l >= 0 and r < n and s[l] == s[r]:
3 l -= 1; r += 1
4 return l + 1, r - 1 # 回文区间(扩过头要收回一格)
5best = (0, 0)
6for i in range(n):
7 for a, b in (expand(i, i), expand(i, i+1)): # 奇 + 偶 中心
8 if b - a > best[1] - best[0]: best = (a, b)复杂度分析
- 时间复杂度:O(n²) —— n 个中心 × 每个最多扩 n
- 空间复杂度:O(1) —— 只用几个指针
套路模板
记住骨架:一个 expand 函数、每个位置试奇偶两种中心、相等就向外扩。回文子串数(647)就是把"记录最长"换成"累加每次扩成功的次数"。
Python
1def expand(l, r):
2 while l >= 0 and r < n and s[l] == s[r]: # 两边相等就扩
3 l -= 1; r += 1
4 return r - l - 1 # 回文长度
5for i in range(n):
6 odd = expand(i, i) # 奇中心
7 even = expand(i, i + 1) # 偶中心易错点
- ❌ 只考虑奇数长度中心 → ✅ 奇 (i,i) 和偶 (i,i+1) 都要试("abba" 这种偶回文中心在两字符之间)
- ❌ 区间边界算错 → ✅ while 停后回文是 [l+1, r-1](循环退出时 l、r 已各多走一步)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。