<manacher>神族文字

1 篇文章 0 订阅
1 篇文章 0 订阅

题意

给你一个长度为n的字符串,让你求最长的回文子串长度。

数据范围

对于30%的数据,字符串长度≤1000
对于60%的数据,字符串长度≤〖10〗^6
对于100%的数据,字符串长度≤5*〖10〗^6,字符串仅包含小写字母

分析

明显的manacher,直接用manacher求一遍即可。

补充manacher

其实就是一个更新,看看现在的与以前的有没有关系,若有便可以继续更新,所以这是线性的。

由于这个算法是线性从前往后扫的。那么当我们准备求P[i]的时候,i以前的P[j]我们是已经得到了的。我们用mx记在i之前的回文串中,延伸至最右端的位置。同时用id这个变量记下取得这个最优mx时的id值。(注:为了防止字符比较的时候越界,我在这个加了‘#’的字符串之前还加了另一个特殊字符‘$’,故我的新串下标是从1开始的)

这里写图片描述

模板
mid:=0;
        les:=0;
        le:=le*2+1;
        for i:=1 to le do begin
            if les<=i then p[i]:=1 else p[i]:=min(p[mid*2-i],les-i);
            while (i+p[i]<=le)and(i-p[i]>=1)and(st[i-p[i]]=st[i+p[i]]) do//拓展
            inc(p[i]);
            if p[i]+i>les then begin
               les:=p[i]+i;
               mid:=i;
            end;
        end;

代码:

var i,len,ans,mid,les:longint;p:array[0..15000000] of longint;str:ansistring;
    st:array[0..15000000] of char;
function max(l,r:longint):longint;
begin
    if l<r then exit(r) else exit(l);
end;
function min(l,r:longint):longint;
begin
    if l>r then exit(r) else exit(l);
end;
begin
    readln(str);
    len:=length(str);
    st[1]:='#';
    for i:=1 to len do begin
        st[i*2]:=str[i];
        st[i*2+1]:='#';
    end;
    les:=0;mid:=0;len:=len*2+1;
    for i:=1 to len do begin
        if les<=i then p[i]:=1 else p[i]:=min(p[mid*2-i],les-i);
        while (i+p[i]<=len)and(i-p[i]>=1)and(st[i+p[i]]=st[i-p[i]]) do inc(p[i]);
        if p[i]+i>les then begin
           les:=p[i]+i;
           mid:=i;
        end;
    end;
    for i:=1 to len do ans:=max(ans,p[i]-1);
    writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值