其他分享
首页 > 其他分享> > HDU 4513吉哥系列故事——完美队形II Manacher

HDU 4513吉哥系列故事——完美队形II Manacher

作者:互联网

HDU 4513吉哥系列故事——完美队形II Manacher

题意

吉哥又想出了一个新的完美队形游戏!
假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形:

  1. 挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的;
  2. 左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意;
  3. 从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] .... <= H[mid]

现在吉哥想知道:最多能选出多少人组成新的完美队形呢?

解题思路

看到这里序列的特殊要求实际上不就是个回文串嘛,那肯定就是Manacher算法了。

关键是如何处理大小关系呢,这里是在模板中加了一些判断就可以解决:

  1. 中间插入的不再是字符,而是数字,这里我们插入0x3f3f3f3f这个来进行代替。
  2. 在判断完对称的数字相等之后还要判断是否小于,这里需要知道两个实际的数之间有我们插的数,这个需要注意。
  3. 其他细节看代码。

代码实现

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e5+7;
int num[maxn], tmp[maxn<<1];
int p[maxn<<1]; 
int t, n;
void init()
{
    tmp[0]=inf+1;
    for(int i=1; i<=2*n; i+=2)
    {
        tmp[i] = inf;
        tmp[i+1] = num[i>>1];
    }
    tmp[(n<<1)+1]=inf;
    tmp[(n<<1)+2]=inf+1;
}
int manacher(int *st, int len)
{
    int mx=0, ans=0, po=0;
    for(int i=1; i<=len; ++i)
    {
        if(mx > i)
            p[i]=min( mx-i, p[ (po<<1) - i ] );
        else 
            p[i]=1;
        while(st[ i - p[i]] ==st[ i + p[i]] )
        {
            if( st[ i-p[i] ] == inf)
                p[i]++;
            else if(st[ i-p[i] ] <= st[ i-p[i]+2 ])
                p[i]++;
            else break;
        }
        if(p[i]+i>mx)
        {
            mx=p[i]+i;
            po=i;
        }
        ans=max(ans, p[i]);
    }
    return ans-1;
}
int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(int i=0; i<n; i++)
            scanf("%d", &num[i]);
        init();
//      for(int i=1; i<=2*n+1; i++)
//          printf("%d ", tmp[i]);
//      printf("\n");
        int ans=manacher(tmp, n*2+1);
        printf("%d\n", ans);
    }
    return 0;
 } 

标签:HDU,int,4513,II,完美,maxn,Manacher,吉哥,队形
来源: https://www.cnblogs.com/alking1001/p/12248537.html