zoukankan      html  css  js  c++  java
  • HDU4513 【mannacher算法】

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4513

    Problem Description
      吉哥又想出了一个新的完美队形游戏!
      假设有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]。
      现在吉哥想知道:最多能选出多少人组成新的完美队形呢?
    Input
      输入数据第一行包含一个整数T,表示总共有T组测试数据(T <= 20);
      每组数据首先是一个整数n(1 <= n <= 100000),表示原先队形的人数,接下来一行输入n个整数,表示原队形从左到右站的人的身高(50 <= h <= 250,不排除特别矮小和高大的)。
    Output
      请输出能组成完美队形的最多人数,每组输出占一行。
     
    思路:
    1.要求选出的人在原队列中连续且想对顺序不变,即连续的子串
    2.该连续的子串中,左右对称,即连续回文子串。
    3.限制条件:选出的队列呈现“凸字形”
    4.最长,到此题意清晰,发现可以用mannacher算法来写,只是要注意在求解p[]数组时要加上题目限制条件
    代码:
     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<string.h>
     4 #define mem(a, b) memset(a, b, sizeof(a))
     5 using namespace std;
     6 const int MAXN = 1e5 + 100;
     7 const int inf = 0x3f3f3f3f;
     8 
     9 int n;
    10 int a[MAXN], s[2 * MAXN], len, p[2 * MAXN];
    11 
    12 void get_s() //为了避免因 奇数偶数长度的串 引起的讨论,直接构造新的数列
    13 {
    14     s[0] = -inf;
    15     s[1] = -1;
    16     len = 1;
    17     for(int i = 1; i <= n; i ++)
    18     {
    19         s[++ len] = a[i];
    20         s[++ len] = -1;
    21     }
    22     s[++ len] = inf;  //防止越界 s[0] 与 s[len]必须不相同 
    23 }
    24 
    25 int mannacher()
    26 {
    27     int mx = 0, id = 0, maxlen = -1;
    28     mem(p, 0); //每个点的最长回文半径初始化为 0  
    29     for(int i = 1; i < len; i ++) //除去了边界
    30     {
    31         if(i < mx)//先获取该点的回文半径当前最长长度 待更新 
    32             p[i] = min(p[id - (i - id)], mx - i);
    33         else
    34             p[i] = 1;
    35         while(s[i - p[i]] == s[i + p[i]] && s[i - p[i]] <= s[i - p[i] + 2]) //限制条件 
    36             p[i] ++;
    37         if(i + p[i] > mx)
    38         {
    39             mx = i + p[i];
    40             id = i;
    41         }
    42         maxlen = max(maxlen, p[i] - 1);
    43     }
    44     return maxlen;
    45 }
    46 
    47 int main()
    48 {
    49     int T;
    50     scanf("%d", &T);
    51     while(T --)
    52     {
    53         scanf("%d", &n);
    54         len = 0;
    55         for(int i = 1; i <= n; i ++)
    56             scanf("%d", &a[i]);
    57         get_s();
    58         int ans = mannacher();
    59         printf("%d
    ", ans);
    60     }
    61     return 0;
    62 }
    mannacher
  • 相关阅读:
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    英文标点
    post sharp 与log4net 结合使用,含执行源码 转拷
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/11265216.html
Copyright © 2011-2022 走看看