647.回文子串
647.回文子串
解题思路:
中心扩散法
Manacher 算法
package leadcode;
/**
* @author : icehill
* @description : 回文子串
* 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
* 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
* 示例 1:
* 输入:"abc"
* 输出:3
* 解释:三个回文子串: "a", "b", "c"
* 示例 2:
* 输入:"aaa"
* 输出:6
* 解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
* 提示:
* 输入的字符串长度不会超过 1000 。
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/palindromic-substrings
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
* @date : 2021-05-28
*/
public class Solution647 {
public static void main(String[] args) {
Solution647 solution647 = new Solution647();
System.out.println(solution647.countSubstrings("aaaa"));
}
/**
* Manacher 算法
* 时间复杂度:O(n)空间复杂度:O(n)
* @param s
* @return
*/
public int countSubstrings(String s) {
int n = s.length();
StringBuffer t = new StringBuffer("$#");
for (int i = 0; i < n; ++i) {
t.append(s.charAt(i));
t.append('#');
}
n = t.length();
t.append('!');
int[] f = new int[n];
int iMax = 0, rMax = 0, ans = 0;
for (int i = 1; i < n; ++i) {
// 初始化 f[i]
f[i] = i <= rMax ? Math.min(rMax - i + 1, f[2 * iMax - i]) : 1;
// 中心拓展
while (t.charAt(i + f[i]) == t.charAt(i - f[i])) {
++f[i];
}
// 动态维护 iMax 和 rMax
if (i + f[i] - 1 > rMax) {
iMax = i;
rMax = i + f[i] - 1;
}
// 统计答案, 当前贡献为 (f[i] - 1) / 2 上取整
ans += f[i] / 2;
}
return ans;
}
/**
* 中心扩散法
* 时间复杂度:O(n^2)空间复杂度:O(1)
* @param s
* @return
*/
public int countSubstringsTwo(String s) {
int count=0;
for(int i=0;i<2*s.length()-1;i++){
// left和right指针和中心点的关系是?
// 首先是left,有一个很明显的2倍关系的存在,其次是right,可能和left指向同一个(偶数时),也可能往后移动一个(奇数)
// 大致的关系出来了,可以选择带两个特殊例子进去看看是否满足。
int left = i / 2;
int right = left + i % 2;
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
count++;
left--;
right++;
}
}
return count;
}
}