[Luogu P4555] [BZOJ 2565] [国家集训队]最长双回文串

本文介绍了一种解决寻找最长双回文子串问题的方法,利用正反两个方向建立回文自动机来求解。具体步骤包括构建回文自动机、通过跳转更新状态、插入字符并记录答案等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

洛谷传送门
BZOJ传送门

题目描述

顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同)。

输入长度为 n n n的串 S S S,求 S S S的最长双回文子串 T T T,即可将 T T T分为两部分 X X X Y Y Y,( ∣ X ∣ , ∣ Y ∣ ≥ 1 |X|,|Y|≥1 X,Y1)且 X X X Y Y Y都是回文串。

输入输出格式

输入格式:

一行由小写英文字母组成的字符串 S S S

输出格式:

一行一个整数,表示最长双回文子串的长度。

输入输出样例

输入样例#1:
baacaabbacabb
输出样例#1:
12

说明

【样例说明】

从第二个字符开始的字符串aacaabbacabb可分为aacaabbacabb两部分,且两者都是回文串。

对于100%的数据, 2 ≤ ∣ S ∣ ≤ 1 0 5 2≤|S|≤10^5 2S105

解题分析

回文自动机板题, 因为回文自动机的 l e n len len指的是以当前点结尾的回文串的最大长度, 所以正反建两个回文自动机, 跑一跑就好了。

代码如下:

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define MX 200500
struct PAM
{
    int len[MX], fail[MX], to[MX][26], str[MX], ans[MX];
    int cnt, n, cur, last;
    IN int _nw(R int val) {len[cnt] = val; return cnt++;}
    IN void reset()
    {
        cnt = 0, _nw(0), _nw(-1);
        n = last = cur = 0; str[0] = -1;
        fail[0] = 1;
    }
    IN int jump(R int now)
    {
        W (str[n] != str[n - len[now] - 1]) now = fail[now];
        return now;
    }
    IN void insert(R int id)
    {
        str[++n] = id; R int now = jump(last);
        if(!to[now][id])
        {
            cur = _nw(len[now] + 2);
            fail[cur] = to[jump(fail[now])][id];
            to[now][id] = cur;
        }
        last = to[now][id]; ans[n] = len[last];
    }
}p1, p2;
char dat[MX];
int l;
int main(void)
{
    p1.reset(); p2.reset();
    scanf("%s", dat + 1); l = std::strlen(dat + 1);
    for (R int i = 1; i <= l; ++i) p1.insert(dat[i] - 'a');
    std::reverse(dat + 1, dat + 1 + l);
    for (R int i = 1; i <= l; ++i) p2.insert(dat[i] - 'a');
    int ans = 0;
    for (R int i = 1; i <= l; ++i) ans = std::max(ans, p1.ans[i] + p2.ans[l - i]);
    printf("%d", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值