• 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
    ", 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
    ", 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
  • 相关阅读:
    判断 iframe 是否加载完毕
    iframe跨端口报错 Blocked a frame with origin from accessing a cross-origin frame
    React与Vue
    原生js监听input值发生变化
    防抖函数与节流函数
    原生js 实现better-scroll效果,饿了么菜单内容联动,即粘即用
    力扣数据库的一些题解
    动态代理
    一个能够进行增删改查的数组的构建(数据结构01)
    c语言学习笔记(1)
  • 原文地址:https://www.cnblogs.com/orchidzjl/p/5694879.html
Copyright © 2020-2023  润新知