网站面包屑导航怎么做的腾讯广告联盟官网
求回文子串
LeetCode 647
思路参考这里
代码实现
class Solution {
public:// Manacher 模板int countSubstrings(string s) {// [STEP1] 修改源字符串// 将 s 改造为 t,这样就不需要讨论 s.length() 的奇偶性,因为新串 t 的每个回文子串都是奇回文串(都有回文中心)// s 和 t 的下标转换关系:// (si+1)*2 = ti// ti/2-1 = si// ti 为偶数,对应奇回文串(从 2 开始)// ti 为奇数,对应偶回文串(从 3 开始)string t = "^";for (char c : s) {t += '#';t += c;}t += "#$";// [STEP2] 计算回文半径// 定义一个奇回文串的回文半径=(长度+1)/2,即保留回文中心,去掉一侧后的剩余字符串的长度// half_len[i] 表示在 t 上的以 t[i] 为回文中心的最长回文子串的回文半径// 即 [i-half_len[i]+1,i+half_len[i]-1] 是 t 上的一个回文子串vector<int> half_len(t.length() - 2);half_len[1] = 1;int ans = 0;// box_r 表示当前右边界下标最大的回文子串的右边界下标+1// box_m 为该回文子串的中心位置,二者的关系为 r=mid+half_len[mid]int box_m = 0, box_r = 0;for (int i = 2; i < half_len.size(); i++) {int hl = 1;if (i < box_r) {// 记 i 关于 box_m 的对称位置 i'=box_m*2-i// 若以 i' 为中心的最长回文子串范围超出了以 box_m 为中心的回文串的范围(即 i+half_len[i'] >= box_r)// 则 half_len[i] 应先初始化为已知的回文半径 box_r-i,然后再继续暴力匹配// 否则 half_len[i] 与 half_len[i'] 相等hl = min(half_len[box_m * 2 - i], box_r - i);}// 暴力扩展// 算法的复杂度取决于这部分执行的次数// 由于扩展之后 box_r 必然会更新(右移),且扩展的的次数就是 box_r 右移的次数// 因此算法的复杂度 = O(t.length()) = O(n)while (t[i - hl] == t[i + hl]) {hl++;box_m = i;box_r = i + hl;}half_len[i] = hl;ans += hl / 2;}return ans;}
};