P4287 [SHOI2011]双倍回文 解题报告

Desciption

给定一个字符串 s, 求 s 的最长双倍回文子串。

双倍回文串定义为长度为4的倍数,并且满足 WWRWWR形式的字符串。

WR 为字符串 W 的倒置。长度为偶数的普通回文串的形式为 WWR

Solution

~~貌似是 PAM 的基础题,不过我暂时不会。~~

看到回文串考虑 manachar。我们发现在 manachar 的实现过程中实际上证明了一个性质,就是一个串的本质不同的回文子串的个数是 O(n) 的。而产生一个新的本质不同回文子串只有可能在更新 mx 的时候出现,这个时候直接暴力对每个新产生的回文子串判断一下即可。于是做完啦。

Code

复制代码
#include<bits/stdc++.h>
using namespace std;
inline int read() {
    int x = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -f; c = getchar();}
    while (c >= '0' && c <= '9') {x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}
    return x * f;
}
const int N = 5e5 + 10;
int n, p[N<<1];
char s[N], str[N<<1];
inline void manachar() {
    int len = 1, ans = 0; str[0] = '$'; str[1] = '#';
    for (int i = 1; i <= n; ++ i) str[++len] = s[i], str[++len] = '#';
    for (int i = 1, mx = 0, id = 0; i <= len; ++ i) {
        if (i < mx) p[i] = min(p[2*id-i], mx - i);
        else p[i] = 1;
        while (str[i+p[i]] == str[i-p[i]]) ++p[i];
        if (i + p[i] > mx) {
            if (i & 1) for (int j = max(mx, i + 4); j < i + p[i]; ++ j)
                if (!(j-i & 3) && p[i-(j-i)/2] > (j-i)/2) ans = max(ans, j - i);
            mx = i + p[i], id = i;
        }
    }
    printf("%d\n", ans);
}
int main () {
    n = read(); scanf("%s", s + 1);
    manachar();
    return 0;
}
View Code
复制代码

 

posted @   LikC1606  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示