leetcode:647. 回文子串
题目
给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入:s = "abc"输出:3解释:三个回文子串: "a", "b", "c"
示例 2:
输入:s = "aaa"输出:6解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
解答 & 代码
解法一:中心扩展法(双指针)
外循环遍历每种可能的回文中心,然后内循环以这个回文中心为起点向两边扩展
需要注意的是,回文中心可能是一个数(回文子串长度为奇数)也可能是相邻的两个数(回文子串长度为偶数)。因此可以用两个变量 mid1、mid2 来代表回文子串中心的下标。如果 mid1==mid2,则回文中心是一个数,否则是相邻的两个数。
eg. 长为 3 的字符串,回文子串中心的下标取值 (mid1, mid2) 依次为 (0, 0)->(0,1),->(1,1)->(1,2)->(2,2)
class Solution {public:int countSubstrings(string s) {int len = s.size();int result = 0; // 回文子串数目int mid1 = 0; // 回文子串中心 1 下标int mid2 = 0; // 回文子串中心 2 下标// 遍历每对回文子串中心的取值while(mid1 < len && mid2 < len){int left = mid1; // 回文子串的左边界int right = mid2; // 回文子串的右边界// 从回文子串中心向两边扩展while(left >= 0 && right < len && s[left] == s[right]){++result; // 回文子串数目 +1--left;++right;}// 回文子串中心右移if(mid1 < mid2)++mid1;else++mid2;}return result;}};
复杂度分析:设字符串 s 长为 N
- 时间复杂度
:外循环遍历回文子串中心,需要迭代 2N-1 次。内循环从中心向两边扩展,时间复杂度 O(N)
- 空间复杂度 O(1)
执行结果:
执行结果:通过执行用时:0 ms, 在所有 C++ 提交中击败了 100.00% 的用户内存消耗:6.2 MB, 在所有 C++ 提交中击败了73.93% 的用户
解法二:Manacher 算法(马拉车算法)
复杂度分析:设字符串 s 长为 N
- 时间复杂度 O(N)
- 空间复杂度 O(N)
