• 【HDOJ 5371】 Hotaru's problem


    【HDOJ 5371】 Hotaru’s problem

    Manacher算法+穷举/set

    Manacher算法一好文:http://blog.csdn.net/yzl_rex/article/details/7908259

    套一个Manacher算出回文半径数组p之后 有两种方法
    穷举法:
    枚举-1的点(依据题意仅仅必为偶数回文) 找在该点回文半径内与其相隔最远 而且回文半径等于他俩距离(即两点为中心的回文串同样) 的点 记录找到时的距离 不断枚举找最大值即为最大回文串长 串长/2*3即为答案

    set法:
    记录-1的位置 依据每一个-1相应的回文半径排序 从大到小枚举增加set 每增加一个位置i后 查找大于i-p[i]的第一个数(lower_bound) 和小于等于i+p[i]的第一个数(–upper_bound) 该位置与这两个位置的距离即为各自组成的回文串长度的二分之中的一个 找到最大的*3即为答案

    代码例如以下:

    //穷举
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    
    using namespace std;
    
    int nwm[200002];
    int p[200002];
    
    void Manacher(int n)//马拉车模板
    {
        nwm[0] = -2;
        int i;
        for(i = 0; i < n; i++)
        {
            nwm[i*2+1] = -1;
            scanf("%d",&nwm[i*2+2]);
        }
        nwm[n*2+1] = -1;
        nwm[n*2+2] = -3;
        int maxid = 0,id;
        n = n*2+2;
        for(i = 2; i < n; ++i)
        {
            if(maxid > i) p[i] = min(p[id*2-i],maxid-i);
            else p[i] = 1;
    
            while(nwm[i+p[i]] == nwm[i-p[i]]) p[i]++;
    
            if(p[i]+i > maxid)
            {
                maxid = p[i]+i;
                id = i;
            }
        }
    }
    
    int main()
    {
        int t,n,z = 0,i,mm,x;
        scanf("%d",&t);
        while(t--)
        {
            mm = 0;
            scanf("%d",&n);
            Manacher(n);
    
            for(i = 3; i +4< n*2+2; i+=2)//枚举-1
            {
                if(p[i]-1 > mm)
                {
                    x = p[i]-1;//记录-1为中心的最大回文串长
                    while(x > mm && p[i+x] < x)//枚举找满足题意的第二回文中心
                        x--;
                    mm = max(mm,x);
                }
            }
    
            printf("Case #%d: %d
    ",++z,mm/2*3);
        }
        return 0;
    }
    //set方法
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <set>
    #include <algorithm>
    
    using namespace std;
    
    int nwm[200002];
    int p[200002];
    int id[200002],tp;
    set <int> s;
    
    void Manacher(int n)
    {
        nwm[0] = -2;
        int i;
        for(i = 0; i < n; i++)
        {
            nwm[i*2+1] = -1;
            id[tp++] = i*2+1;//将-1位置记录
            scanf("%d",&nwm[i*2+2]);
        }
        nwm[n*2+1] = -1;
        nwm[n*2+2] = -3;
        int maxid = 0,id;
        n = n*2+2;
        for(i = 2; i < n; ++i)
        {
            if(maxid > i) p[i] = min(p[id*2-i],maxid-i);
            else p[i] = 1;
    
            while(nwm[i+p[i]] == nwm[i-p[i]]) p[i]++;
    
            if(p[i]+i > maxid)
            {
                maxid = p[i]+i;
                id = i;
            }
        }
    }
    
    bool cmp(int a,int b)//按-1相应回文距离由大到小排序
    {
        return p[a] > p[b];
    }
    
    int main()
    {
        int t,n,z = 0,i,mm,x,l,r;
    
        scanf("%d",&t);
        while(t--)
        {
            s.clear();
            tp = 0;
            mm = 0;
            scanf("%d",&n);
            Manacher(n);
            sort(id,id+tp,cmp);
            for(i = 0; i < tp; ++i)//回文距离从大到小枚举位置
            {
                s.insert(id[i]);
                l = *s.lower_bound(id[i]-p[id[i]]);//找左边第一个>=id[i]-p[id[i]]的位置
                r = *(--s.upper_bound(id[i]+p[id[i]]));//找右边第一个<=id[i]+p[id[i]]的位置
                mm = max(mm,max(id[i]-l,r-id[i]));
            }
            printf("Case #%d: %d
    ",++z,mm/2*3);
        }
    
        return 0;
    }
    
  • 相关阅读:
    hdu6007 Mr. Panda and Crystal 最短路+完全背包
    ID生成器的一种可扩展实现方案
    使用PUT方法上传文件无法工作原因分析
    负载均衡算法
    父类和子类属性覆盖的各种情况分析
    java functional syntax overview
    Starter Set of Functional Interfaces
    application/xml和text/xml的区别
    mime type 概要介绍
    spring mvc 详细执行流程
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7233551.html
Copyright © 2020-2023  润新知