hdoj 5371 Hotaru's problem

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

这道题用到了Manacher算法,首先简单介绍一下Manacher算法:

----------------------------------------------------------------------------------------------

【转】http://blog.csdn.net/yzl_rex/article/details/7908259

一个专门针对回文子串的算法,其时间复杂度为O(n)

求回文串时需要判断其奇偶性,也就是求aba 和abba 的算法略有差距。然而,这个算法做了一个简单的处理,

很巧妙地把奇数长度回文串与偶数长度回文串统一考虑,也就是在每个相邻的字符之间插入一个分隔符,

串的首尾也要加,当然这个分隔符不能再原串中出现,一般可以用‘#’或者‘$’等字符。

这样一来,原来的奇数长度回文串还是奇数长度,偶数长度的也变成以‘#’为中心奇数回文串了。

接下来就是算法的中心思想,用一个辅助数组P 记录以每个字符为中心的最长回文半径,

也就是P[i]记录以Str[i]字符为中心的最长回文串半径。P[i]最小为1,此时回文串为Str[i]本身。

核心代码:

1 if (maxid > i){
2              p[i] = min(p[2*id - i], maxid - i);
3          }

-----------------------------------------------------------------------------------------------

再回到本题,因为所给的数列为非负整数,所以用-1作为间隔,利用Manacher算法求出各点的最长回文,

然后因为 abbaab 可以理解为 abba 和 baab 两个回文串,所以在第一个回文串的末尾往回找,

如果回文串的长度大于两点之间的距离,且大于sum,则更新sum。

在遍历过程中进行简化,易知回文串必然是偶数个的,所以只遍历-1的点就可以了。

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int MAXN = 200050;
 6     int str[MAXN];
 7     int p[MAXN];
 8     int N;
 9 int main(){
10     int T;
11     int TT = 0;
12     int mx, pi;
13     int _max;
14     int j;
15     scanf("%d",&T);
16     while(T--){
17         memset(p,0,sizeof(p));
18         memset(str,0,sizeof(str));
19         str[0] = -100;
20         str[1] = -1;
21         scanf("%d",&N);
22         getchar();
23         N = N * 2 + 1;
24         for(int i = 2; i < N; i++){
25             if( i % 2 == 0)
26                 scanf("%d",&str[i]);
27             else str[i] = -1;
28         }
29         str[N++] = -1;
30         int lgt = N;
31         mx = 0; pi = 1;
32         for( int i = 1; i < lgt; i = i + 1){
33             if(str[i] == -1){
34                 if( i < mx)
35                     p[i] = min(p[2*pi-i],mx-i);
36                 else
37                     p[i] = 1;
38                 while( str[i-p[i]] == str[i+p[i]])
39                     p[i]++;
40                 if( p[i]+i > mx ){
41                     pi = i;
42                     mx = p[i]+i;
43                 }
44             }
45         }
46         _max = 0;
47         for(int i = 1; i < lgt; i = i + 1){
48             if( p[i] > _max && str[i] == -1){
49                 while( j > lgt) j -= 2;
50                 for( j = i + p[i] - 1; j - i + 1 > _max; j -= 2 ){
51                     if( p[j] >= j - i + 1)
52                         _max = j - i + 1;
53                 }
54             }
55         }
56         printf("Case #%d: %d\n",++TT,(_max-1)/2*3);
57     }
58 }

hdoj 5371 Hotaru's problem

时间: 2024-08-27 15:58:41

hdoj 5371 Hotaru's problem的相关文章

HDOJ 5371 Hotaru&#39;s problem manacher+优先队列+二分

先用求回文串的Manacher算法,求出以第i个点和第i+1个点为中心的回文串长度,记录到数组c中 比如 10 9 8 8 9 10 10 9 8 我们通过运行Manacher求出第i个点和第i+1个点为中心的回文串长度 0 0 6 0 0 6 0 0 0 两个8为中心,10 9 8 8 9 10是个回文串,长度是6. 两个10为中心,8 9 10 10 9 8是个回文串,长度是6. 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,比如上边的两个字符串,共享 8 9 10这一

HDU 5371 Hotaru&#39;s problem (Manacher,回文串)

题意:给一个序列,找出1个连续子序列,将其平分成前,中,后等长的3段子序列,要求[前]和[中]是回文,[中]和[后]是回文.求3段最长为多少?由于平分的关系,所以答案应该是3的倍数. 思路:先Manacher求最长子串,利用期间所记录的P 数组,穷举一下所有可能的前两串,再用O(1)时间判断第3串是否符合要求. 具体做法: (1)P[i]记录的是以i为中心,从i-P[i]+1到i+P[i]-1这段都是回文.由于前两段之和必为偶数,所以必须选取str[i]为'#'的. (2)扫一遍每个'#',以其

HDU 5371 Hotaru&#39;s problem manacher+(线段树or set)

题意,给定一个100000 的串,求他一个子串,使得将子串分成三部分有后,第一部分=第三部分,第一部分与第二部分对称(回文) 首先我们需要处理出以i为轴的回文串的两端,这个事情可以用Manacher算法完成,复杂度O(n) http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/ 这个博客写的很好懂.不会的童鞋可以去学习一下这个算法,非常精妙. 好的现在我们已经会了这个算法,并获得了每个点为轴的串的右端点p[i] 很简单地可以处理出左端

hdu 5371 Hotaru&#39;s problem【manacher】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5371 题意: 给出一个长度为n的串,要求找出一条最长连续子串.这个子串要满足:1:可以平均分成三段,2:第一段和第三段相等,3:第一段和第二段回文.求最大子串的长度. 代码: #include<stdio.h> #include<iostream> #include<math.h> #include<stdlib.h> #include<ctype.h&

HDU 5371 Hotaru&#39;s problem(manacher + 枚举啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371 Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is playing with N-sequence. Let's define N-sequence, which is composed with three parts and satisfied with the foll

hdu 5371 Hotaru&#39;s problem(manacher+尺取法)

题意: 给定一个有n个数字的序列,找出一个连续的子序列满足这样的条件: 1. 平均分成三段 2. 第一段与第三段一样 3. 第二段是第一段的倒序.求这样的子序列的最大长度. 数据范围:n~100000 解析: 我看网络上面很多的题解都是用O(n2/32)的做法水数据过去的,这种做法是先用mancher算法预处理出每个每个回文串最远所能抵达的位置,然后枚举每个位置i,再枚举其回文串的长度,然后枚举当前位置i到回文串所能抵达的最远距离,判断途径的位置j是,否有回文串能够到当前位置i.但是这种做法的复

HDU 5371——Hotaru&#39;s problem——————【manacher处理回文】

Hotaru's problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1765    Accepted Submission(s): 635 Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is playing

HDU 5371 Hotaru&#39;s problem

manacher算法介绍 先用求回文串的Manacher算法,求出以第i个点和第i+1个点为中心的回文串长度,记录到数组c中 比如 10 9 8 8 9 10 10 9 8 我们通过运行Manacher求出第i个点和第i+1个点为中心的回文串长度 0 0 6 0 0 6 0 0 0 两个8为中心,10 9 8 8 9 10是个回文串,长度是6. 两个10为中心,8 9 10 10 9 8是个回文串,长度是6. 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,比如上边的两个字符

【HDOJ 5371】 Hotaru&#39;s problem

[HDOJ 5371] Hotaru's problem Manacher算法+穷举/set Manacher算法一好文:http://blog.csdn.net/yzl_rex/article/details/7908259 套一个Manacher算出回文半径数组p之后 有两种方法 穷举法: 枚举-1的点(根据题意只必为偶数回文) 找在该点回文半径内与其相隔最远 并且回文半径等于他俩距离(即两点为中心的回文串相同) 的点 记录找到时的距离 不断枚举找最大值即为最大回文串长 串长/2*3即为答案