题目描述
统计字符串中回文子串的个数(内容相同但位置不同算多个)。
s = "aaa"
输出 = 6
思路解析
和最长回文子串同一个套路:枚举每个奇/偶中心往外扩。区别是——这里不求最长,而是 每次 s[l]==s[r] 成立(扩成功),就发现了一个新回文,计数 +1。
中心 = 下标1 的 a:以中间 a(下标1)为奇中心:自己就是一个回文 "a",count +1。然后继续向两边扩。
扩 · a==a → 又一个回文:l=0、r=2,s[0]==s[2],扩成功!发现回文 "aaa",count 再 +1。继续扩越界停。这个中心贡献了 2 个。
偶中心 = 下标0、1 之间:再试偶中心 (0,1):s[0]==s[1],扩成功,发现 "aa",count +1。每个中心都这样数一遍。
所有中心累计 · 共 6 个:把每个奇中心、偶中心扩出的回文全加起来:3 个 "a" + 2 个 "aa" + 1 个 "aaa" = 6。
最长回文子串是“记录最长”,回文子串是“累加计数”——同一个中心扩展骨架,换一下“收集结果的动作”就解决不同问题。这就是掌握套路的威力。
参考代码(Python)
Python
1count = 0
2def expand(l, r):
3 nonlocal count
4 while l >= 0 and r < n and s[l] == s[r]:
5 count += 1 # 每扩成功一次 = 一个回文
6 l -= 1; r += 1
7for i in range(n):
8 expand(i, i); expand(i, i + 1) # 奇 + 偶 中心
9return count复杂度分析
- 时间复杂度:O(n²) —— n 个中心 × 扩展
- 空间复杂度:O(1) —— 一个计数器
套路模板
记住骨架:奇偶中心都试、相等就扩、扩成功就收集。把“收集”换成计数、记最长、记区间,就分别解 647、5 和其他回文题。
Python
1def expand(l, r):
2 while l >= 0 and r < n and s[l] == s[r]:
3 count += 1 # 收集: 计数(或记最长)
4 l -= 1; r += 1
5for i in range(n): expand(i,i); expand(i,i+1) # 奇+偶易错点
- ❌ 漏了单字符也是回文 → ✅ 奇中心 (i,i) 自带 +1(expand(i,i) 第一次必成立,单字符就被计入)
- ❌ 只数奇中心 → ✅ 奇 + 偶 中心都要数(偶回文(如 "aa")只能从偶中心找到)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。