Manacher(最长递减回文串)

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

  请输出能组成完美队形的最多人数,每组输出占一行。

Sample Input

2
3
51 52 51
4
51 52 52 51

Sample Output

3
4

Source

2013腾讯编程马拉松初赛第二场(3月22日)

Recommend

liuyiding

题意:求最长递减回文串

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <algorithm>
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include <stdio.h>
#include <string.h>
using namespace std;
int a[100009] , b[200009];
int p[200009];

int num;

int main()
{
    int t ;
    scanf("%d" , &t);
    while(t--)
    {
        int l ;
        scanf("%d" , &l);
        for(int i = 0 ; i < l ; i++)
        {
            scanf("%d" , &a[i]);
        }
        int len = 0 ;
        b[len++] = -1;
        b[len++] = -1 ;
        for(int i = 0 ; i < l ; i++)
        {
            b[len++] = a[i];
            b[len++] = -1 ;
        }
        int mx = -1 , mid , ans = 0;
        for(int i = 1 ; i < len ; i++)
        {
            if(mx > i)
            {
                p[i] = min(p[2*mid-i] , mx - i);
            }
            else
            {
                p[i] = 1 ;
            }
            while(b[i-p[i]] == b[i+p[i]] &&  b[i - p[i] + 2] >= b[i - p[i]])//从中间往两边递减
            {
                p[i]++;
            }
            if(mx < p[i] + i)
            {
                mid = i ;
                mx = p[i] + i;
            }
            ans = max(ans , p[i] - 1);
        }
        printf("%d\n" ,ans);
    }

    return 0 ;
}

原文地址:https://www.cnblogs.com/nonames/p/11296260.html

时间: 2024-10-29 11:37:05

Manacher(最长递减回文串)的相关文章

Manacher(最长镜面回文串)

I - O'My! Gym - 101350I Note: this is a harder version of Mirrored string I. The gorillas have recently discovered that the image on the surface of the water is actually a reflection of themselves. So, the next thing for them to discover is mirrored

!HDU 5371 最长双回文串(多校7)-卡时间-(manacher+排序+set+lower_bound())

题意:给定一个有n个数字的序列,找出一个连续的子序列满足这样的条件:平均分成三段,第一段与第三段一样,第二段是第一段的倒序.求这样的子序列的最大长度.数据范围:n~100000 分析: 上面的条件抽象出来其实就是双回文串,所以题目就是求一个序列的最长双回文串. 主体做法是: 1.先用manacher算法O(n)求出每个元素的最大回文半径: 2.把每个元素看成一个圆心,那么两个点能构成双回文串必须满足的条件是他们在对方的圆内或圆上(画个示意图就理解了),所以接下来怎么利用最大回文半径呢.题解是这么

2565: 最长双回文串 - BZOJ

Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串.Input 一行由小写英文字母组成的字符串S. Output 一行一个整数,表示最长双回文子串的长度.Sample Input baacaabbacabb Sample Output 12 HINT

【BZOJ】【2565】最长双回文串

Manacher算法 找出一个最长子串S=X+Y,且X和Y都是回文串,求最长的长度是多少…… 同时找两个串明显很难搞啊……但是我们可以先找到所有的回文串!在找回文串的同时我们可以预处理出来l[i]和r[i]分别表示从 i 这个位置开始向左/右最长的回文串有多长,那么我们枚举两个回文串的分割点更新答案即可. 1 /************************************************************** 2 Problem: 2565 3 User: Tunix

最长(大)回文串的查找(字符串中找出最长的回文串)PHP实现

首先还是先解释一下什么是回文串:就是从左到右或者从右到左读,都是同样的字符串.比如:上海自来水来自海上,bob等等. 那么什么又是找出最长回文串呢? 例如:字符串abcdefedcfggggggfc,其中efe,defed,cdefedc,gg,ggg,gggg,ggggg,gggggg,fggggggf,cfggggggfc都是回文串,左右完全一样. 这其中,有最短的gg,最长的cfggggggfc,还有其他长度的.忽略长度为1的.毕竟一个字符的都算回文了. 那么,找出最长的,就是找出这个cf

BZOJ2565:最长双回文串

2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2195  Solved: 1119[Submit][Status][Discuss] Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都

HYSBZ 2565 最长双回文串 (回文树)

2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1377  Solved: 714 [Submit][Status][Discuss] Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y

【BZOJ2565】最长双回文串 Manacher

题解: 首先我们写一个Manacher模板.. 然后我们可以把所有回文串的信息映射到左端点上, 每个点依此维护最长右连接回文串. 然后再顺着扫一遍就出解了. 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 101000 using namespace std; char ts[N],s[N<<1]; int n,

BZOJ 2565 最长双回文串 Hash+二分

题目大意:给定一个字符串,求一个最长的子串,该字串可以分解为两个回文子串 傻逼的我又忘了Manacher怎么写了= = 无奈Hash+二分吧 首先将字符串用分隔符倍增,然后求出以每个点为中心的最长回文半径 然后考虑两个回文串怎么合并成一个 我们发现图中以i为中心的回文串和以j为中心的回文串合并后长度恰好为(j-i)*2 能合并的前提是以两个点为中心的回文串有交点 那么对于每个j我们要求出有交点的最左侧的i 维护一个后缀min随便搞搞就可以了 #include <cstdio> #include