Manacher [模板]

  • M a n a c h e r 的 作 用 Manacher的作用 Manacher

可以快速得到有关 回文子串 的相关信息 . 板子题

  • M a n a c h e r 的 内 容 Manacher的内容 Manacher

本质上就是对 暴力的优化 和 现有信息的利用 .

暴力寻找回文子串, 无非就是枚举 对称轴, 往两边扩展, 时间复杂度 O ( N 2 ) O(N^2) O(N2) .

m a n a c h e r manacher manacher 则是在暴力的基础上, 利用了前面已经求出的回文子串信息,

具 体 地 说 : 具体地说 : :

设 变量 M a x _ r Max\_r Max_r 表示当前回文串所能触及的 最右端点, m i d mid mid 表示那个触及 M a x _ r Max\_r Max_r 的回文串 的 中点,
且当前到了 i i i 位置, 要以 i i i 为对称轴扩展出所有 连续 回文子串, j j j i i i 关于 m i d mid mid对称点,
h w [ i ] hw[i] hw[i] 表示 i i i 位置的最长回文串 长度的一半 .

  • i i i M a x _ r Max\_r Max_r 代表的回文串内, 则 j j j 为对称轴的回文串 M a x _ r Max\_r Max_r 的 “领地” 里的回文长度可以完全 继承 i i i 位置 .
  • 否则只能暴力扩张 i i i 位置 .

因为 M a x _ r Max\_r Max_r 只扩展到 N N N, 所以 时 间 复 杂 度   O ( N ) 时间复杂度\ O(N)  O(N).

  • M a n a c h e r 的 实 现 Manacher的实现 Manacher

很多情况对称轴为 间隙 也要考虑, 此时可以在字符之间插入 特殊字符 后正常 跑 M a n a c h e r Manacher Manacher.
具体可以看代码 .

#include<bits/stdc++.h>

const int maxn = 21000005;

int Ans;
int hw[maxn<<1];

void Manacher(char *s){
        int max_r = 0, mid = 0;
        int len = strlen(s+1);
        for(int i = 1; i <= len; i ++){
                if(i < max_r) hw[i] = std::min(hw[(mid<<1) - i], max_r-i+1);
                while(i + hw[i] <= len && i - hw[i] >= 1 && s[i + hw[i]] == s[i - hw[i]]) hw[i] ++;
                if(i + hw[i] - 1 > max_r) max_r = i + hw[i] - 1, mid = i;
                Ans = std::max(Ans, hw[i]-1);
        }
}

char s[maxn], s1[maxn<<1];

int main(){
        scanf("%s", s + 1);
        int len = strlen(s+1);
        for(int i = 1; i <= len<<1; i ++){
                if(i & 1) s1[i] = '#';
                else s1[i] = s[i>>1];
        }
        s1[(len<<1)+1] = '#';
        Manacher(s1);
        printf("%d\n", Ans);
        return 0;
}
  • M a n a c h e r 的 应 用 Manacher的应用 Manacher

P 1659 [ 国 家 集 训 队 ] 拉 拉 队 排 练 P1659 [国家集训队]拉拉队排练 P1659[]

P 4555 [ 国 家 集 训 队 ] 最 长 双 回 文 串 P4555 [国家集训队]最长双回文串 P4555[]

P 4199 万 径 人 踪 灭 P4199 万径人踪灭 P4199

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值