O(n)时间求 最长回文子串 Manacher算法

  1. 回文字符串分为奇回文和偶回文,在字符串中间插入任意字符使得串变成奇回文串

暴力思想:肯定是找一个点往两边任意扩展,遍历一次,
Manacher时间为O(n)

  1. 开一个数组p[]记录 以点i为中点 的最长回文串的半径,
  2. 假设前i-1个点的p[]都已经求出来来,现在考虑p[i]如何推导
    网上找来的图片
    重点:
  3. Rp[1]~p[i-1]中推出来的右端最远最长回文子串的右端点,且用pos记录下来,每一步更新pos+R,既然R知道了,L也知道(没啥意义)
  4. 当前遍历到i点,j是与i对称的点,且 j = p o s − ( i − p o s ) j=pos-(i-pos) j=pos(ipos) -> j = 2 p o s − i j=2pos-i j=2posi,我们可以通过j点来得到i点的p[i]
  5. 此时i j R有三种情况
    a. 第一个图中红色都在[L,R]范围内,R-i>p[j],直接得到p[i]的值,p[i]=p[j]
    b.

    此时j点的回文子串只有一部分在[L,R](最大的回文子串)中,那么超出范围的肯定不符合要求,R-i<p[j]所以p[i]=R-i
    c. 剩下一个情况应该都看出来了,就是i>=R,现在只能往两边暴力扩展了

总结步骤:

  1. 先更新p[],有三种情况
  2. 向两边暴力扩展回文字符串,满足前两种情况这一步肯定扩展不出来新的回文串,所以不需要特殊判断是否if(p[i]==1),所以这一步往两边扩展
  3. 更新[L,R]右端最远的回文子串,并且记录pos的值,
  4. 这是(插入字符的奇数字符串)上的一系列操作,我们要转化成源字符串上的位置长度 这里是2个结论,自己对比就可以知道了
    原字符串的位置:index = (resid - reslen)/2
    源字符串的长度:len = reslen-1
  • 在第一个添加一个与其他都不同的字符,就是为了index正确求出来
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
    string t;
    while ( cin>>t && t!="END" ) {
        string s("%#");
        for (int i=0; i<t.size(); i++) {
            s += t[i];
            s += "#";
        }
        vector<int> p(s.size(),0);
        int id=0, mx=0, resid=0, reslen=0;
        for (int i=1; i<s.size(); i++) {
            p[i] = mx > i ? min(p[2*id-i],mx-i):1;
            while ( s[i-p[i]] == s[i+p[i]] ) ++p[i];
            if ( mx<i+p[i] ) {
                mx = i+p[i];
                id = i;
            }
            if ( reslen < p[i] ) {
                reslen = p[i];
                resid = i;
            }
        }
        string ans=t.substr( (resid-reslen)/2 , reslen-1 );//求出来的最长回文子串
        cout << ans.size() << endl;//长度
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值