BZOJ2342 Manacher + set

题一:别人介绍的一道题,题意是给出一个序列,我们要求出一段最常的连续子序列,满足:该子序列能够被平分为三段,第一段和第二段形成回文串,第二段和第三段形成回文串。

题二:BZOJ2342和这题非常的相似,BZOJ的题意是说求出一个最长的回文串,该串能平均分四段,满足整体是回文串,前一半是回文串,后一半也是回文串。

对于第一个问题的做法是:Manacher后,枚举每一个位置i(一定是#),作为第二个中心,那么我们就需要在[i-Mp[i], i]之间找到一个最小的j,满足以j为中心的回文串能够覆盖到位置i, 最先找到的,贡献的答案肯定最大。是不是对于每个位置i,我们都需要在前面找所有的范围内的j呢? jiaru摸个j形成的回文不能覆盖到i, 那么这个j肯定不能覆盖到k(k>i), 即这个j对之后的位置都没有贡献,可以删除, 而每个位置最多被删一次, 复杂度为nlog

 

题二:

复制代码
/**************************************************************
    Problem: 2342
    User: foratrp
    Language: C++
    Result: Accepted
    Time:748 ms
    Memory:18280 kb
****************************************************************/
 
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <stack>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long ll;
const int N = 5e5 + 100;
 
char Ma[N <<1];
int Mp[N << 1];
char s[N];
 
void Manacher(int len) {
    int l = 0;
    Ma[l++] = '$';
    Ma[l++] = '#';
    for(int i = 0; i < len; ++i)
    {
        Ma[l++] = s[i];
        Ma[l++] = '#';
    }
    Ma[l] = 0;
    int mx = 0, id = 0;
    for(int i = 0; i < l; ++i)
    {
        Mp[i] = mx > i ? min(Mp[2 * id - i], mx - i) : 1;
        while (Ma[i + Mp[i]] == Ma[i - Mp[i]]) Mp[i]++;
        if(i + Mp[i] > mx) mx = i + Mp[i], id = i;
    }
   // for(int i = 0; i < l; ++i) printf("%d ", Mp[i]);
}
set<int> ms;
void solve(int n) {
    int ans = 0; ms.clear();
    for(int i = 3; i < 2 * n + 2; i += 2) ms.insert(i);
    for(int i = 5; i < 2 * n + 2; i += 2)
    {
        int j = i - (Mp[i] / 2);
        if(j % 2 == 0) j++;
        while(j != i)
        {
            if(j + Mp[j] > i) { ans = max(ans, (i - j) * 2); break; }
            else { ms.erase(j); j = *ms.lower_bound(j); }
        }
    }
    printf("%d\n", ans);
}
int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif
    int len;
    while(~scanf("%d", &len)) {
        scanf("%s", s);
        Manacher(len);
        solve(len);
    }
    return 0;
}
View Code
复制代码

题一:

复制代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <stack>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long ll;
const int N = 5e5 + 100;

int Ma[N <<1];
int Mp[N << 1];
int s[N];

void Manacher(int len) {
    int l = 0;
    Ma[l++] = -INF;
    Ma[l++] = INF;
    for(int i = 0; i < len; ++i)
    {
        Ma[l++] = s[i];
        Ma[l++] = INF;
    }
    Ma[l] = 0;
    int mx = 0, id = 0;
    for(int i = 0; i < l; ++i)
    {
        Mp[i] = mx > i ? min(Mp[2 * id - i], mx - i) : 1;
        while (Ma[i + Mp[i]] == Ma[i - Mp[i]]) Mp[i]++;
        if(i + Mp[i] > mx) mx = i + Mp[i], id = i;
    }
   //wwww for(int i = 0; i < l; ++i) printf("%d ", Mp[i]);
}
set<int> ms;
void solve(int n) {
    int ans = 0; ms.clear();
    for(int i = 3; i < 2 * n + 2; i += 2) ms.insert(i);
    for(int i = 5; i < 2 * n + 2; i += 2)
    {
        int j = i - Mp[i] + 1;
        while(j != i)
        {
            if(j + Mp[j] > i) { ans = max(ans, (i - j) / 2 * 3); break; }
            else { ms.erase(j); j = *ms.lower_bound(j); }
        }
    }
    printf("%d\n", ans);
}
int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif
    int cas, _ = 1, len;
    scanf("%d", &cas);
    while(cas --) {
        scanf("%d", &len);
        for(int i = 0; i < len; ++i) scanf("%d", &s[i]);
        Manacher(len);

        printf("Case #%d: ", _++);
        solve(len);
    }
    return 0;
}
View Code
复制代码

 

posted @   JL_Zhou  阅读(185)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
历史上的今天:
2015-07-22 Codeforce 546D
点击右上角即可分享
微信分享提示