• bzoj2342


    manacher+set

    好像这种求回文串形态的都是用manacher,然后求出中心之间奇怪的关系

    我们先跑出来manacher,由于只要偶数回文串,我们就只把#位置记录下来,重新保存,然后我们考虑什么情况下区间[x+1,y]*4可以更新答案,x是整个回文串的中心。那么很明显有x+f[x]/2>=y,y-p[y]>=x

    碰见这种情况,我们一般先保证一个不等式恒成立,另一个用数据结构搞一搞,那么我们让y-p[y]>=x恒成立,先对y排个序,然后将满足条件的y逐渐加入,插入set,我们枚举的是x,自然希望y越大越好,那么我们在set里查x+f[x]/2的前继,看能是否更新答案。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 500010;
    int n, len, ans, pos, mx;
    char t[N], s[N << 1];
    int p[N << 1], f[N], y[N];
    set<int> S;
    bool cmp(int i, int j) { return i - f[i] < j - f[j]; }
    int main()
    {
        scanf("%d%s", &n, t + 1);
        s[0] = '!';
        s[len = 1] = '#';
        for(int i = 1; i <= n; ++i) s[++len] = t[i], s[++len] = '#'; 
        for(int i = 1; i <= len; ++i) 
        {
            if(i < mx) p[i] = min(mx - i, p[2 * pos - i]); else p[i] = 1;
            while(s[i - p[i]] == s[i + p[i]]) ++p[i];
            if(i + p[i] > mx)
            {
                pos = i;
                mx = i + p[i];
            }
        }
        for(int i = 1; i <= n; ++i) f[i] = (p[i << 1 | 1] - 1) >> 1, y[i] = i;
        sort(y + 1, y + n + 1, cmp);
        int j = 0;
        for(int i = 1; i <= n; ++i)
        {
            while(y[j + 1] - f[y[j + 1]] <= i && j < n) ++j, S.insert(y[j]);
            set<int> :: iterator it = S.upper_bound(i + (f[i] >> 1));
            if(it == S.begin()) continue;
            else --it;
            if(i + (f[i] >> 1) >= *it && *it - f[*it] <= i) ans = max(ans, (*it - i) * 4);
        }
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    bzoj3653: 谈笑风生
    bzoj1858: [Scoi2010]序列操作
    bzoj1857: [Scoi2010]传送带
    bzoj1856: [Scoi2010]字符串
    bzoj1855: [Scoi2010]股票交易
    bzoj1854: [Scoi2010]游戏
    bzoj1853: [Scoi2010]幸运数字
    斜堆,非旋转treap,替罪羊树
    NOI2003 文本编辑器
    A_star poj2449 k短路
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7552497.html
Copyright © 2020-2023  润新知