【HDOJ 5371】 Hotaru's problem

来源:互联网 发布:邮箱都有哪些域名 编辑:程序博客网 时间:2024/05/20 06:29

【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;}
0 0
原创粉丝点击