zoukankan      html  css  js  c++  java
  • 【BZOJ2342】双倍回文(SHOI2011)-Manacher+set

    测试地址:双倍回文
    做法:本题需要用到Manacher+set。
    首先看到回文子串,跑一遍Manacher是免不了的了,关键在于如何利用这些信息求最长的双倍回文子串。
    考虑枚举整个串的对称轴x(显然这个对称轴一定是两个字符之间的位置),令f(x)x这个位置的最长回文半径,即以这个位置为对称轴的最长回文子串的半长,那么对于之后的一个位置y,定义这个yx合法当且仅当存在一个子串,使得它关于x回文,而x之后的部分关于y回文。于是yx合法的条件等价于:yf(y)x,x+f(x)2y。显然如果一个yx合法,4(yx)就是一个合法的答案。
    注意到在x增长时,满足第一个条件的y只会增多,因此我们把yyf(y)排序后依次插入。那么我们只需要求出当x一定时,同时满足第二个条件的最大的y,即可用4(yx)更新答案,这可以用set维护。于是我们就解决了这一题,时间复杂度为O(nlogn)
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    int n,f[500010];
    char s[500010];
    struct forsort
    {
        int id,val;
    }F[500010];
    set<int> S;
    set<int>::iterator it;
    
    bool cmp(forsort a,forsort b)
    {
        return a.val<b.val;
    }
    
    void init()
    {
        scanf("%d",&n);
        scanf("%s",s);
    }
    
    void manacher()
    {
        s[n]='#';
        f[0]=0;
        int last=0,r=0;
        for(int i=1;i<=n;i++)
        {
            if (i<=r&&i+f[(last<<1)-i]<r)
                f[i]=f[(last<<1)-i];
            else
            {
                int l;
                if (i>r) l=i-1,r=i,f[i]=0;
                else f[i]=min(r-i,f[(last<<1)-i]),l=r-(f[i]<<1)-1;
                while(s[l]==s[r]) l--,r++,f[i]++;
                last=i;
            }
        }
    }
    
    void work()
    {
        for(int i=0;i<=n;i++)
        {
            F[i].val=i-f[i];
            F[i].id=i;
        }
        sort(F,F+n+1,cmp);
    
        int ans=0,now=1;
        for(int i=0;i<=n;i++)
        {
            while(now<=n&&F[now].val<=i)
            {
                S.insert(F[now].id);
                now++;
            }
            it=S.upper_bound(i+f[i]/2);
            if (it==S.begin()) continue;
            it--;
            if (it==S.begin()) continue;
            ans=max(ans,(*it)-i);
        }
        printf("%d",ans<<2);
    }
    
    int main()
    {
        init();
        manacher();
        work();
    
        return 0;
    }
  • 相关阅读:
    什么是Code Review
    支撑5亿用户、1.5亿活跃用户的Twitter最新架构详解及相关实现
    shell的数组操作
    CDN(内容分发网络)技术原理
    云计算服务模型,第 3 部分: 软件即服务(PaaS)
    Mongodb
    360的开源项目
    用linux mail命令发送邮件[Linux]
    BZOJ2761:[JLOI2011]不重复数字(map)
    BZOJ1821:[JSOI2010]部落划分(并查集,二分)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793331.html
Copyright © 2011-2022 走看看