【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\n",++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\n",++z,mm/2*3);
    }

    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

【HDOJ 5371】 Hotaru's problem

时间: 2024-10-08 21:02:06

【HDOJ 5371】 Hotaru's problem的相关文章

【HDOJ 5402】Travelling Salesman Problem

[HDOJ 5402]Travelling Salesman Problem 一开始以为是搜索 仔细画了画发现就一模拟 奇数行或奇数列的时候怎么走都能全走完 偶数行偶数列的时候就要挑了 . * . * . * * . * . * . . * . * . * * . * . * . 以4*6为例(如上图 星号可以保证不取其中一个可遍历完全图 点好的话就会连带一些星号 所以绕过星号中的最小值 是最佳遍历方式 输入的时候找到最小值并记录下行列 遍历到改行前以 右走到头 下 左走到头 下 右走到头这种方

【HDOJ 1002】A + B Problem II

A + B Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 238517    Accepted Submission(s): 45969 Problem Description I have a very simple problem for you. Given two integers A and B, you

【HDOJ 4763】 Theme Section (KMP+strstr)

[HDOJ 4763] Theme Section Theme Section Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1999    Accepted Submission(s): 947 Problem Description It's time for music! A lot of popular musicians a

【HDOJ 4768】 Flyer (等差数列+二分)

[HDOJ 4768] Flyer (等差数列+二分) Flyer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2022    Accepted Submission(s): 743 Problem Description The new semester begins! Different kinds of student soc

【HDOJ 5834】Magic boy Bi Luo with his excited tree(树型DP)

[HDOJ 5834]Magic boy Bi Luo with his excited tree(树型DP) Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Bi Luo is a magic boy, he also has a migic tree,

【HDOJ 5654】 xiaoxin and his watermelon candy(离线+树状数组)

pid=5654">[HDOJ 5654] xiaoxin and his watermelon candy(离线+树状数组) xiaoxin and his watermelon candy Time Limit: 4000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 233    Accepted Submission(s): 61 Problem Des

【HDOJ 5838】Mountain(局部极小值)

[HDOJ 5838]Mountain(局部极小值) Mountain Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Zhu found a map which is a N * M rectangular grid.Each cell has a height and there are no two cells which have

【HDOJ 5653】 Bomber Man wants to bomb an Array.(DP)

[HDOJ 5653] Bomber Man wants to bomb an Array.(DP) Bomber Man wants to bomb an Array. Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 389    Accepted Submission(s): 117 Problem Description Give

【HDOJ 5652】 India and China Origins(并查集)

[HDOJ 5652] India and China Origins(并查集) India and China Origins Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 805    Accepted Submission(s): 272 Problem Description A long time ago there are