zoukankan      html  css  js  c++  java
  • 【BZOJ】2342: [Shoi2011]双倍回文(Manacher)

    题目

    传送门:QWQ

    分析

    (sb如我写了发不知道什么东西在洛谷上竟然水了84分

    嗯咳

    设$ i $为双重回文的中心

    如果$ j~i $ 可以被算作答案,只有满足如下两式:

    • $ p[j]+j geq i $
    • $ 2*(i-j) leq p[j] $

    计算时我们先做一次马拉车,然后按照 $ p[j]+j geq i $排序,保证它的单调,接着把满足$ 2*(i-j) leq p[j] $扔进set里询问。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1050000;
    char s2[maxn],s[ maxn];
    int p[ maxn], len;
    set<int> t;
    void Manacher(){
        len=strlen(s2+1);
        for(int i=1;i<=len;i++){
            s[i*2-1]='#'; s[i*2]=s2[i];
        }
         s[len=len*2+1]='#'; 
         int right=0, pos=0;
         for(int i=1;i<=len;i++){
             if(i<right){ p[i]=min(p[2*pos-i],right-i); } else p[i]=0;
            while(i+p[i]<=len &&i-p[i]>0 && s[i+p[i]]==s[i-p[i]]) p[i]++;
            if(i+p[i]>right){
                right=i+p[i]; pos=i;
            }
         }
    }
    int q[maxn], f[maxn];
    bool cmp(int a,int b){ return (a-f[a])<(b-f[b]); }
    int main(){
        int n;
        scanf("%d%s",&n,s2+1); 
        Manacher();
        for(int i=1;i<=n;i++) q[i]=i, f[i]=(p[i*2+1]-1)/2;
        sort(q+1,q+1+n,cmp);
        int now=1,ans=0;
        for(int i=1;i<=n;i++){
            while(now<=n&&q[now]-f[q[now]]<=i) {
                t.insert(q[now]);
                now++;
            }
            set<int>::iterator tmp=t.upper_bound(i+f[i]/2);
            if(tmp!=t.begin ()){
                ans=max(ans,(*--tmp - i));
            }
        }
        printf("%d
    ",ans*4);
        return 0;
    }
    /*
    17
    qwertyuaabbaabbaa
    */
  • 相关阅读:
    1032. Sharing (25)
    1031. Hello World for U (20)
    1030. Travel Plan (30)
    1029. Median (25)
    1028. List Sorting (25)
    1026. Table Tennis (30)
    win10 tortoiseSVN文件夹及文件图标不显示解决方法
    qrcode.react和jquery.qrcode生成二维码
    js来获取所有屏幕适配的总结
    handsontable整理
  • 原文地址:https://www.cnblogs.com/noblex/p/9191804.html
Copyright © 2011-2022 走看看