回文自动机模板

P

uses math;
var
        len,fai,cnt,num:array[0..300000]of int64;
        next:array[0..300000,'a'..'z']of longint;
        p,n,last,now,cur,i:longint;
        ans:int64;
        ss:ansistring;
        s:array[0..300000]of char;
function get_fail(x:longint):longint;
var
        sss:longint;
begin
        sss:=x;
        while s[n-len[sss]-1]<>s[n] do
                sss:=fai[sss];
        exit(sss);
end;
begin
        readln(ss);
        fillchar(s,sizeof(s),0);
        s[0]:='[';
        p:=2;
        len[0]:=0;
        len[1]:=-1;
        fai[0]:=1;
        fai[1]:=1;
        last:=0;
        n:=1;
        for i:=1 to length(ss) do
        begin
                inc(n);
                s[n]:=ss[i];
                while s[n]<>s[n-len[last]-1] do
                        last:=fai[last];
                cur:=last;
                if next[cur][s[n]]=0 then
                begin
                        now:=p;
                        inc(p);
                        len[now]:=len[last]+2;
                        fai[now]:=next[get_fail(fai[cur])][s[n]];
                        next[cur][s[n]]:=now;
                end;
                last:=next[cur][s[n]];
                inc(cnt[last]);
        end;
        for i:=p-1 downto 1 do
        begin
                inc(cnt[fai[i]],cnt[i]);
                inc(ans,cnt[i]);
        end;
        writeln(ans);
end.

题目:
https://jzoj.net/senior/#main/show/3654

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值