回文子串
647. 回文子串 - 力扣(LeetCode) (leetcode-cn.com)
方法1:中心扩展--遍历中心/遍历中心种类
假设字符串长度n=4。
| 回文左起始位置 | 回文右起始位置 | |
| 0 | 0 | 0 |
| 1 | 0 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 2 |
| 5 | 2 | 3 |
| 6 | 3 | 3 |
可以看出中心种类有7中,可得公式s=2*n-1,代码如下;
方法2:manacher算法
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;//rMax-i+1防止f[2*iMax-i]过大超过右边界
// 中心拓展
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,所以除二即可
ans += f[i] / 2;
}
return ans;
}
时间复杂度:O(n))。即 Manacher 算法的时间复杂度,由于最大回文右端点 r_mrm只会增加而不会减少,故中心拓展进行的次数最多为 O(n)O(n),此外我们只会遍历字符串一次,故总复杂度为 O(n)O(n)。
空间复杂度:O(n)。
浙公网安备 33010602011771号